缓存中间件
2022-12-15 11:14:41 0 举报
AI智能生成
缓存中间件 知识图 思维导图 Redis
作者其他创作
大纲/内容
缓存
数据
使用方式
静态数据: 一般不变,类似字典表(男、女)
准静态数据:变化频率低,比如:部门结构、全国行政区域划分
中间状态数据:一些计算可复用的中间数据、变量副本、配置中心的本地副本
使用频率
热数据:使用频率高
读写比较大: 读的频率>>写的频率
广义上:为了加速数据处理、让业务更快访问的临时存放的冗余数据。狭义上:内存缓存(分布式系统缓存到内存的数据)
内存(CPU与磁盘之间的缓存);L1&L2 Cache(CPU与内存处理速度不一致时出现);网络处理、数据库引擎的各种buffer
读写比(N:1维护成本)、命中率(90%+有价值)。对于 数据一致性、性能、成本综合考量,是引入缓存的必须指标
缓存失效、缓存命名
本地缓存
HashMap
Hibernate/Mybatis缓存
一级缓存 Session级别
二级缓存 SessionFactory级别
<cache type ="org.mybatis.caches.ehcache.LoggingEhcache">
<property name="memoryStoreEvictionPolicy" value="LRU"/>
</cache>
<select id="selectArticleListPage" resultMap="resultUserArticleList" useCache="false">
<property name="memoryStoreEvictionPolicy" value="LRU"/>
</cache>
<select id="selectArticleListPage" resultMap="resultUserArticleList" useCache="false">
<propery name ="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<ehcache><diskStore path ="/tmp/cache" /></ehcache>
<cache usage ="read-write" />
<class name ="Student" table ="t_student" ><cache usage ="read-write"/> </class>
<ehcache><diskStore path ="/tmp/cache" /></ehcache>
<cache usage ="read-write" />
<class name ="Student" table ="t_student" ><cache usage ="read-write"/> </class>
Guava Cache
Cache<String,String> cache = CacheBuilder.newBuilder()
.maximumSize(1024) // 设置构建缓存容器的最大容量,当缓存数量达到该容量时,会删除其中的缓存(根据实际测试结果,会先删除先放入的数据)
.expireAfterWrite(60,TimeUnit.SECONDS) // 访问后多久过期
.weakValues()
.build();
//缓存数据 cache.put("cache","cache-value");
//获取缓存数据 Stringvalue=cache.getIfPresent("cache");
//删除缓存 cache.invalidate("cache5");
.maximumSize(1024) // 设置构建缓存容器的最大容量,当缓存数量达到该容量时,会删除其中的缓存(根据实际测试结果,会先删除先放入的数据)
.expireAfterWrite(60,TimeUnit.SECONDS) // 访问后多久过期
.weakValues()
.build();
//缓存数据 cache.put("cache","cache-value");
//获取缓存数据 Stringvalue=cache.getIfPresent("cache");
//删除缓存 cache.invalidate("cache5");
Caffeine
Spring Cache
1、基于注解和AOP,使用非常方便
2、可以配置Condition和SPEL,非常灵活
3、需要注意:绕过Spring的话,注解无效
2、可以配置Condition和SPEL,非常灵活
3、需要注意:绕过Spring的话,注解无效
核心功能:@Cacheable、@CachePut、@CacheEvict
远程缓存
Memcached
Memcached 官网:https://memcached.org/
Redis
Redis 官网:https://redis.io/
Redis 在线测试:http://try.redis.io/
Redis 命令参考:http://doc.redisfans.com/
《Redis 设计与实现》:http://redisbook.com/
hazelcast内存网格
Ignite内存网格
支持SQL
缓存策略
思考系统的 设计容量、使用容量、峰值
过期策略
FIFO
LRU(Least Recently Used)最近最少使用
按固定时间过期
按业务时间加权 例如: 3+5X
缓存加载时机
启动全量加载 => 全局有效 使用简单
懒加载
同步使用加载
先看缓存是否有数据,没有从数据库读取;读取数据 ①先放入内存 ②然后返回给调用方
延迟异步加载
从缓存获取数据,不管是否为空直接返回
策略1:如果为空,则发起一个异步加载的线程,负责加载数据
策略2:异步线程负责维护缓存的数据,定期或者根据条件触发更新
缓存常见问题
穿透
问题:大量并发查询不存在的key、查询到一个空值,导致直接将压力透传到数据库
解决方案
1、缓存空值的KEY,第一次不存在时会被加载记录,下次拿到这个KEY
2、Bloom过滤 或 RoaringBitmap 判断KEY是否存在
3、完全以缓存为准,使用 延迟异步加载 的策略2,这样就不会触发更新
击穿
问题:某个KEY失效的时候,正好有大量的并发请求访问这个KEY
解决方案
1、KEY的更新操作,追加 全局互斥锁
2、完全以缓存为准,使用 延迟异步加载 的策略2,这样就不会触发更新
雪崩
问题:当某一时刻,发生大规模缓存失效情况,会有大量的请求直接打到数据库,导致数据库压力过大升值宕机
分析:由于更新策略、数据热点、缓存服务宕机等原因,可能会导致缓存数据同一个时间点大规模不可用,或者都更新。所以,需要我们的更新策略在时间上合适,数据要均匀分散,缓存服务器要多台高可用
解决方案
① 更新策略在时间上做到比较均匀
② 使用的热数据尽量分散到不同的机器上
③ 多台机器做主从复制 或 多副本,实现高可用
④ 实现熔断限流机制,对系统进行负载能力控制
redis
安装
brew、apt、yum安装
docker
docker pull redis
docker run -itd --name redis-test -p 6379:6379 redis
docker image inspect redis:latest|grep -i version
docker run -itd --name redis-test -p 6379:6379 redis
docker image inspect redis:latest|grep -i version
docker exec -it redis-test /bin/bash
$ redis-cli
> info
$ redis-cli
> info
新入门注意的坑:没有redis.conf文件
$ docker run -p 6379:6379 --name redis01 -v
/etc/redis/redis.conf:/etc/redis/redis.conf -v /etc/redis/data:/data -d redis
redis-server /etc/redis/redis.conf --appendonly yes
/etc/redis/redis.conf:/etc/redis/redis.conf -v /etc/redis/data:/data -d redis
redis-server /etc/redis/redis.conf --appendonly yes
性能测试
redis-benchmark
10万次32个链接 redis-benchmark -n 100000 -c 32 -t SET,GET,INCR,HSET,LPUSH,MSET -q
redis-benchmark -n 100000 -c 32 -t SET,GET,INCR,HSET,LPUSH,MSET -q
数据结构
5种基础数据结构
字符串(String)
二进制byte[],可以接收任何格式数据 value最大 512M
set/get/getset/del/exists/append
当做整数 incr/decr/incrby/decrby
incr age / incrby age 2
注意
1、字符串append:会使用更多的内存
2、int 整数共享:如果能使用整数,就尽量使用整数(限制了Redis内存+LRU)
3、整数精度问题:redis大概能保持16位,17-18位大整数容易丢失精确
散列(Hash)
hset/hget hmset/hmget hgetall
hdel/hexists hincrby
hlen hkeys/hvals
列表(List)
lpush/rpush
lpush list a b c
lrange
lrange list 0 1
lpop/rpop
集合(Set)
sadd/srem
smembers/sismember
sdiff/sinter/sunion 集合求差集,求交集,求并集
有序集合(sorted set)
zadd key score member score2 member2... : 将成员以及该成员的分数存放到sortedset中
3种高级数据结构
Bitmaps
bitmaps不是一个真实的数据结构。而是String类型上的一组面向bit操作的集合。由于
strings是二进制安全的blob,并且它们的最大长度是512m,所以bitmaps能最大设置
2^32个不同的bit
strings是二进制安全的blob,并且它们的最大长度是512m,所以bitmaps能最大设置
2^32个不同的bit
setbit/getbit/bitop/bitcount/bitpos
Hyperloglogs
在redis的实现中,您使用标准错误小于1%的估计度量结束。这个算法的神奇在于不再
需要与需要统计的项相对应的内存,取而代之,使用的内存一直恒定不变。最坏的情况
下只需要12k,就可以计算接近2^64个不同元素的基数。
需要与需要统计的项相对应的内存,取而代之,使用的内存一直恒定不变。最坏的情况
下只需要12k,就可以计算接近2^64个不同元素的基数。
pfadd/pfcount/pfmerge
GEO
Redis3.2版本中推出,这个功能可以将用户给定的地理位置(经
度和纬度)信息储存起来,并对这些信息进行操作。
度和纬度)信息储存起来,并对这些信息进行操作。
geoadd/geohash/geopos/geodist/georadius/georadiusbymember
Redis线程问题
IO线程: redis6(2020年5月)之前 单线程;redis6之后,多线程 NIO模型
内存处理线程: 单线程 ==>高性能的核心
Redis进程是多个线程的
Redis六大使用场景
1、业务数据缓存*
1、通用数据缓存,string、int、list、map等
2、实时热数据,最新500条
3、会话缓存、token缓存
2、业务数据处理
1、非严格一致性要求的数据:评论、点击等
2、业务数据去重:订单处理的幂等性校验
3、业务数据排序: 排名、排行榜
3、全局一致性计数*
1、全局流控技术
2、秒杀的库存计算
3、抢红包
4、全局ID生成
4、高效统计计数
1、id去重,记录访问ip等全局bitmap操作
2、UV、PV等访问量 ==>非严格一致性要求 Hyperloglogs
5、发布订阅与Stream
Pub-Sub 模拟队列
eg: publish comments java / subscribe comments
Redis Stream
Redis 5.0 版本新增加的数据结构
Redis Stream 主要用于消息队列(MQ,Message Queue)
具体可以参考 https://www.runoob.com/redis/redis-stream.html
6、分布式锁*
1、获取锁
SET dlock my_random_value NX PX 30000
2、释放锁--lua脚本-保证原子性+单线程,从而具有事务性
if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end
return redis.call("del",KEYS[1])
else
return 0
end
关键点:原子性、互斥、超时
Redis客户端
Jedis
官方客户端,对redis命令包装。基于BIO,线程不安全,需要配置连接池管理连接
Lettuce
基于Netty NIO,API线程安全。目前主流推荐驱动
Redission
基于Netty NIO,API线程安全
亮点:大量丰富的分布式功能特性,比如JUC的线程安全集合和工具的分布式版本,分
布式的基本数据类型和锁等。
布式的基本数据类型和锁等。
Redis与Spring整合
Spring Data Redis
核心是 RedisTemplate(可以配置基于Jedis,Lettuce,Redisson)
使用方式类似于MongoDBTemplate,JDBCTemplate或JPA
封装了基本redis命令操作
Spring Boot与Redis集成
引入 spring-boot-starter-data-redis
配置 spring redis
Spring Cache与Redis集成
默认使用全局的CacheManager自动集成
使用ConcurrentHashMap或ehcache时,不需要考虑序列化问题。
redis的话,需要:
1、默认使用java的对象序列化,对象需要实现Serializable
2、自定义配置,可以修改为其他序列化方式
1、默认使用java的对象序列化,对象需要实现Serializable
2、自定义配置,可以修改为其他序列化方式
Redis高级功能
Redis事务
- Redis 事务命令:
开启事务:multi
命令入队
执行事务:exec
撤销事务:discard
命令入队
执行事务:exec
撤销事务:discard
- Watch 实现乐观锁
watch 一个key,发生变化则事务失败
子主题
0 条评论
下一页