Redis「2」缓存一致性与异常处理
01-Redis 与 DB 的数据一致性问题
当使用 Redis 作为数据库的缓存时,不得不考虑的一个问题是如何保证缓存(Redis)中数据与数据库中数据的一致性问题。这里的一致性有两种情况(引自[1]):
缓存中有数据,一致性指缓存中数据与数据库中数值保持一致。
缓存中没有数据,一致性指数据库中的指为最新值。
不符合上述两种情况的,就是所谓的不一致性问题。
根据 Redis 缓存是否需要处理写请求,可将 Redis 缓存分为只读缓存和读写缓存。
读写缓存。
增、删、改操作都需要在缓存中操作,然后需要有写回策略(同步策略)将缓存中的内容写入数据库。
写回操作可以是同步的,也可以是异步的。同步写回时,需要事务支持,可保证一致性。异步写回时,若异步写库出现问题,则需要重试机制保证最终写库成功,否则会出现不一致。
只读缓存。
增、删、改操作都直接写库,但在删、改操作时,需要将缓存中的数据删除(或者标记为无效)。
增操作时,直接在数据库中增加,无需操作缓存。满足前面的的第二条(缓存中没数据,数据库中为最新值),缓存一致性成立。
删、改操作时,如果更新数据、标记缓存无效的动作不能保证同时完成(原子性),则可能出现缓存不一致。具体来说:
删除时,若数据库删除成功,缓存标记失败,则后续读取该数据的操作获得的都是缓存中的旧值。
更新时,若数据库更新成功,标记缓存失败,则后续读取操作获得的也是之前的旧值。
此时可采用延时双删来解决。
或者增加队列记录不成功的缓存标记动作,重复直至成功。
但这两种方法,都会让缓存和数据库在一定时间段内存在不一致的情况,此时主要考虑的是业务对这段时间的容忍度。
关于写缓存、数据的的套路,建议参考陈皓的一篇文章[2]。
[1] 25-缓存异常(上):如何解决缓存和数据库的数据不一致问题
[2] 缓存更新的套路
02-Redis 缓存异常及应对方案
02.1-缓存雪崩
缓存雪崩指 Redis 缓存中大量地值同时(或短时间内)失效,导致大量地请求发送到数据库层,导致数据库压力激增的现象。
解决方案:
当业务上有需求数据需要同时失效时,为大量可能同时失效的数据在失效时间上增加一个随机数,将同时失效的数据均匀地分散在一段时间内,减轻数据库可能承受的压力。
或者是使用服务降级来应对缓存雪崩。
[1]中提供的两个建议:1)在业务系统中实现熔断或限流机制;2)提前预防,Redis 做好高可用集群配置
02.2-缓存击穿
缓存击穿指针对某个访问非常频繁的热点数据的请求无法在 Redis 处理,而导致请求涌入到数据库层,从而导致数据库服务器压力激增。解决方案:
对热点数据不设置过期时间
02.3-缓存穿透
缓存穿透指要访问的数据既不在 Redis 中,也不在数据库中,请求到达 Redis 后都不能被处理,最终被提交到数据库访问层,导致数据库服务器压力激增。
解决方案:
在业务设计时,增加缓存空值或缺省指,当发生缓存穿透时,对缓存中不存在的,直接返回空值或缺省值。
在 Redis 中实现布隆过滤器,避免去数据库中查询数据存在与否,减轻数据库压力。
可以在前端请求是增加过滤机制,将明显非法的请求直接从源头屏蔽。
[1] 26-缓存异常(下):如何解决缓存雪崩、击穿、穿透难题
02.4-其他应对策略
前面三个小节中提到的问题,其实主要是数据库服务器对请求的处理能力有限,当大量请求到来时,服务器因压力过大而崩溃。解决问题的思路也很直接,只需要控制数据库服务器承受的压力。例如加锁排队。先获得锁,才能访问数据库,本质上减少同时访问数据库的数量。
往期文章
版权声明: 本文为 InfoQ 作者【Samson】的原创文章。
原文链接:【http://xie.infoq.cn/article/69c5bdbb30200e93e38694038】。文章转载请联系作者。
评论