关联文章
这篇主要讲redis的7大经典问题
一、缓存失效
缓存失效就是我们查redis时,找不到数据,这时就只能去DB中找,最后重新写入到缓存,并返回。当我们查询时,能直接在redis中找到,就是命中缓存,所以如何避免缓存批量失效,穿透到 DB,导致的服务器压力倍增呢。
缓存失效又有几种情况:
1、大面积的缓存key失效
- 失效时间设为base+random,使redis的失效时间在一段时间内随机分布
- 利用LRU/LFU算法,处理淘汰缓存
2、热点key失效
- 先查DB,加锁重构缓存,锁内对缓存进行二次查询,释放锁,走redis查询。优点:简单通用 缺点:用户体验差、锁粒度粗
- 缓存降级:返回不成功,重构缓存,返回数据
- 做备份缓存:一人查DB,其余查备份缓存
二、缓存穿透
缓存穿透就是当业务系统发起查询时,首先在缓存中查询,缓存中不存在,会前往数据库中查询,数据压根就不存在,因此数据库也返回空,然后持续大量的用这种空数据请求服务,就会使业务层穿透redis直达数据库,导致数据I/O压力大增。
针对这种情况我们可以有几种应对方式:
1、将数据库查询结果为空的key也存储在缓存中,针对这类数据设置一个较短的过期时间,让其自动剔除
2、BloomFilter(布隆过滤器),当业务系统有查询请求的时候,首先去BloomFilter中查询该key是否存在。若不存在,则说明数据库中也不存在该数据,因此缓存都不要查了,直接返回null。
3、set/get操作进行相应的盼空或者标示前缀操作
三、缓存雪崩
缓存雪崩是一个非常严重的问题。缓存雪崩是指部分缓存节点不可用,导致整个缓存体系甚至甚至服务系统不可用的情况。
针对节点问题,我们可以采用:
1、增加DB读写开关,慢查询超过阀值,关闭开关,failfast
2、多副本cache架构,任何cache池miss后,读其他cache副本
3、实时监控,及时发现并恢复,增加自动故障转移策略
四、数据不一致问题:
同一份数据,可能会同时存在 DB 和缓存之中。那就有可能发生,DB 和缓存的数据不一致。如果缓存有多个副本,多个缓存副本里的数据也可能会发生不一致现象。不一致的问题大多跟缓存更新异常有关。比如更新 DB 后,写缓存失败,从而导致缓存中存的是老数据。另外,如果系统采用一致性 Hash 分布,同时采用 rehash 自动漂移策略,在节点多次上下线之后,也会产生脏数据。缓存有多个副本时,更新某个副本失败,也会导致这个副本的数据是老数据。
1、cache中数据与DB数据不一致
- 更新DB后,更新cache失败,cache存的是老数据
- 采用rehash自动漂移策略,在节点多次上下线之后,也会产生脏数据
2、多个cache副本 不同cache副本中的数据 不一致
解决方案:
- cache更新失败后,重试or延迟删除
- 调短过期时间,DB重新加载,最终一致性
- 拒绝rehash漂移,采用缓存分层策略
五、数据并发竞争
所谓redis 的并发竞争,通俗地说就是多客户端同时并发写一个 key,可能本来应该后修改的数据先修改到了,导致数据的版本错乱,或者是多客户端同时获取一个 key,修改值之后再写回去,只要顺序错了,数据就错了。
解决方案:
- 可以使用独占锁的方式,类似操作系统的mutex机制。
- 使用乐观锁的方式进行解决(成本较低,非阻塞,性能较高)
- 缓存数据保持多个备份,减少miss的概率
六、HOT KEY
突发热门事件,特定key所在的cache节点服务过载、卡顿、cache
解决方案:
- 找出Hot key、提前预定解决方案。
- 批处理任务离线计算,大数据Hadoop找出最高频key
- Spark流任务实时分析,及时发现新发布的热门key
七、BIG KEY
部分Key的Value过大,读写、加载易超时
解决方案:
1、针对memcached
- 设置缓存阈值,超过阈值即启用压缩
- 启动后预写足够数量大的大key,预分配对应slab
2、针对redis
-
Client序列化,RESTORE一次写入
3、Big key 分拆为多个小key,尽量避免Big kv 过期或剔除