写点什么

Redis「2」缓存一致性与异常处理

作者:Samson
  • 2022 年 5 月 13 日
  • 本文字数:1401 字

    阅读完需:约 5 分钟

Redis「2」缓存一致性与异常处理

01-Redis 与 DB 的数据一致性问题

当使用 Redis 作为数据库的缓存时,不得不考虑的一个问题是如何保证缓存(Redis)中数据与数据库中数据的一致性问题。这里的一致性有两种情况(引自[1]):

  1. 缓存中有数据,一致性指缓存中数据与数据库中数值保持一致。

  2. 缓存中没有数据,一致性指数据库中的指为最新值。


不符合上述两种情况的,就是所谓的不一致性问题。


根据 Redis 缓存是否需要处理写请求,可将 Redis 缓存分为只读缓存和读写缓存。

  1. 读写缓存。

  2. 增、删、改操作都需要在缓存中操作,然后需要有写回策略(同步策略)将缓存中的内容写入数据库。

  3. 写回操作可以是同步的,也可以是异步的。同步写回时,需要事务支持,可保证一致性。异步写回时,若异步写库出现问题,则需要重试机制保证最终写库成功,否则会出现不一致。

  4. 只读缓存。

  5. 增、删、改操作都直接写库,但在删、改操作时,需要将缓存中的数据删除(或者标记为无效)。

  6. 增操作时,直接在数据库中增加,无需操作缓存。满足前面的的第二条(缓存中没数据,数据库中为最新值),缓存一致性成立。

  7. 删、改操作时,如果更新数据、标记缓存无效的动作不能保证同时完成(原子性),则可能出现缓存不一致。具体来说:

  8. 删除时,若数据库删除成功,缓存标记失败,则后续读取该数据的操作获得的都是缓存中的旧值。

  9. 更新时,若数据库更新成功,标记缓存失败,则后续读取操作获得的也是之前的旧值。

  10. 此时可采用延时双删来解决。

  11. 或者增加队列记录不成功的缓存标记动作,重复直至成功。

  12. 但这两种方法,都会让缓存和数据库在一定时间段内存在不一致的情况,此时主要考虑的是业务对这段时间的容忍度。


关于写缓存、数据的的套路,建议参考陈皓的一篇文章[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-其他应对策略

前面三个小节中提到的问题,其实主要是数据库服务器对请求的处理能力有限,当大量请求到来时,服务器因压力过大而崩溃。解决问题的思路也很直接,只需要控制数据库服务器承受的压力。例如加锁排队。先获得锁,才能访问数据库,本质上减少同时访问数据库的数量。


往期文章

Redis「1」流水线、事务、Lua 脚本

发布于: 刚刚阅读数: 5
用户头像

Samson

关注

还未添加个人签名 2019.07.22 加入

还未添加个人简介

评论

发布
暂无评论
Redis「2」缓存一致性与异常处理_Redis 核心技术与实战_Samson_InfoQ写作社区