1. 过期策略
key的⽣存时间到了,Redis会⽴即删除吗?不会⽴即删除。
Redis的过期策略——“定期删除+惰性删除” 。
1、定期删除
定期删除是指Redis默认每隔100ms就随机抽取 N 个设置了过期时间的key,检测这些key是否过期,如果过期了就将其删除。
- 100ms:在Redis的配置文件redis.conf中有一个属性 hz,默认为10,表示1s执行10次定期删除,即每隔100ms执行一次,可以修改这个配置值。
- N 个key:N 同样是由redis.conf文件中的 maxmemory-samples 属性决定的,默认为5。
2、惰性删除
- 惰性删除不是去主动删除,而是在你要获取某个key 的时候,redis会先去检测一下这个key是否已经过期,如果没有过期则返回给你,如果已经过期了,那么redis会删除这个key,不会返回给你。
2、淘汰机制
在配置文件redis.conf 中,可以通过参数 maxmemory
来设定最大内存,不设定该参数默认是无限制的。当内存不足时,就会采取内存淘汰机制,Redis内存淘汰方式有以下八种:
淘汰策略 | 描述 |
volatile-lru | 在内存不⾜时,Redis会在设置过了⽣存时间的key中⼲掉⼀个最近最少使⽤的key |
allkeys-lru | 在内存不⾜时,Redis会在全部的key中⼲掉⼀个最近最少使⽤的key |
volatile-lfu | 在内存不⾜时,Redis会在设置过了⽣存时间的key中⼲掉⼀个最近最少频次使⽤的key |
allkeys-lfu | 在内存不⾜时,Redis会在全部的key中⼲掉⼀个最近最少频次使⽤的key |
volatile-random | 在内存不⾜时,Redis会在设置过了⽣存时间的key中随机⼲掉⼀个 |
allkeys-random | 在内存不⾜时,Redis会在全部的key中随机⼲掉⼀个 |
volatil-ttl | 在内存不⾜时,Redis会在设置过了⽣存时间的key中⼲掉⼀个剩余⽣存时间最少的key |
noeviction | 在内存不⾜时,直接报错,默认值 |
在配置文件redis.conf 中,可以通过参数
maxmemory-policy
来设置淘汰的方式。
过期策略用于处理过期的缓存数据;内存淘汰策略用于处理内存不足时的需要申请额外空间的数据。所以内存淘汰策略的选取并不会影响过期的key的处理。
设置
Redis
的最⼤内存:
maxmemory 字节⼤⼩
3. Redis缓存问题
1. 缓存穿透
名词解释:即请求缓存中不存在的数据,导致所有的请求都怼到数据库上,从而数据库连接异常。
解决方案:
1. 缓存空对象当存储层未命中后,即使数据库返回的空对象也对其进⾏缓存,同时设置⼀个过期时间,之后再访问这个数据将会从缓存中获取,保护了后端数据源。2. 布隆过滤器布隆过滤器是⼀种数据结构,对所有可能查询的参数以 hash 形式存储,在控制层进⾏校验,不符合则丢弃,从⽽避 免了对底层存储系统的查询压⼒。它的优点是空间效率和查询时间都远远超过⼀般的算法,缺点是有⼀定的误识别率和删除困难。3. 设置可访问的⽩名单使⽤ bitmaps 类型定义⼀个可以访问的名单,名单 id 作为 bitmaps 的偏移量,每次访问和 bitmap ⾥⾯的 id 进⾏⽐ 较,如果访问id 不在 bitmaps ⾥⾯,进⾏拦截,不允许访问。4. 进⾏实时监控当发现 Redis 的命中率开始急速降低,需要排查访问对象和访问的数据,和运维⼈员配合,可以设置⿊名单限制服务。
2. 缓存击穿
缓存击穿(热点key)
名词解释:是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。
解决方案:
1. 预先设置热⻔数据在 Redis ⾼峰访问之前,把⼀些热⻔数据提前存⼊到 Redis ⾥⾯,加⼤这些热⻔数据 key 的时⻓。2. 设置热点数据永不过期若缓存的数据是基本不会发⽣更新的,则可尝试将该热点数据设置为永不过期。3. 实时调整现场监控哪些数据热⻔,实时调整 key 的过期时⻓。4. 使⽤分布式锁使⽤分布式锁,保证对于每个 key 同时只有⼀个线程去查询后端服务,其他线程在没有获取分布式锁的权限时,需 要等待。这种⽅式将⾼并发的压⼒转移到了分布式锁,因此对于分布式锁的考验很⼤。5. 定时线程若缓存的数据更新频繁或者在缓存刷新的流程耗时较⻓的情况下,可以利⽤定时线程在缓存过期前主动地重新构建 缓存或者延后缓存的过期时间,以保证所有的请求能⼀直访问到对应的缓存。
3. 缓存雪崩
缓存雪崩(缓存失效)
名词解释:即缓存同一时间大面积的失效,这个时候又来了一波请求,结果请求都怼到数据库上,从而导致数据库连接异常。
解决方案:
1. 构建集群通过搭建 Redis 集群,保障 Redis 的⾼可⽤,避免全盘崩溃。2. 搭建多级缓存架构Nginx 缓存 + Redis 缓存 + 其他缓存( Ehcache 等)。3. 限流降级在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量,从⽽避免失效时⼤量的并发请求落到底层存储系统上。⽐如对某个key 只允许⼀个线程查询数据和写缓存,其他线程等待。不适⽤⾼并发情况。4. 数据预热在正式部署之前,先把可能的数据先预先访问⼀遍,这样部分可能⼤量访问的数据就会加载到缓存中,在即将发⽣⼤并发访问前⼿动触发加载缓存不同的key ,设置不同的过期时间,让缓存失效的时间点尽量均匀。5. 设置过期标志更新缓存记录缓存数据是否过期(设置提前量),如果过期会触发通知另外的线程在后台去更新实际 key 的缓存。6. 将缓存失效时间分散开⽐如我们可以在原有的失效时间基础上增加⼀个随机值,⽐如 1-5 分钟随机,这样每⼀个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。