Redis 如何保证redis缓存和数据库的一致性

 Redis 三种缓存模式(旁路缓存、读写穿透、异步缓存写入)的对比:

策略名称描述流程优点缺点
旁路缓存
(Cache-Aside)
 
- 服务端需要同时维系 DB和 cache并且是以 DB 的结果为准
- 应用程序直接管理缓存,缓存与数据库解耦
- 读时先查缓存,未命中则读数据库并回填缓存;写时直接更新数据库,再删除缓存
 
1. 读操作:
- 查缓存 → 命中返回,未命中读数据库 → 回填缓存
2. 写操作:
- 更新数据库 → 删除缓存
- 缓存与数据库解耦,灵活性高。
- 避免缓存与数据库数据不一致。
- 实现简单
- 缓存未命中时可能引发“缓存击穿”
- 写操作后需手动维护缓存一致性
- 首次读取延迟较高
读写穿透
(Read-Through/Write-Through)
- 缓存作为数据库的代理层,应用仅与缓存交互
- 读穿透由缓存自动加载数据库数据;写穿透同步更新缓存和数据库
1. 读操作:
- 查缓存 → 未命中时缓存层自动从数据库加载数据并存储
2. 写操作:
- 更新缓存 → 同步更新数据库
- 应用无需关心数据库交互,代码简洁
- 保证缓存与数据库强一致性
- 适合读多写少场景
- 缓存层需深度集成数据库逻辑,实现复杂
- 写操作延迟较高(需同步写库)
- 缓存层可能成为性能瓶颈
异步缓存写入
(Write-Behind)
- 写操作先更新缓存,异步批量更新数据库
- 读操作直接访问缓存,数据库最终一致
1. 读操作:
- 仅查缓存
2. 写操作:
- 更新缓存 → 异步批量或延迟更新数据库
- 写性能极高(异步落库)
- 减少数据库压力,适合写密集型场景
- 缓存始终可用,即使数据库暂时故障
- 数据可能丢失(缓存故障时未落库的数据)
- 实现复杂(需队列/重试机制)
- 数据库与缓存短期不一致

系统中最常用的缓存策略是:旁路缓存 

1:读取数据

在单独从redis里面读取数据时,不会出现数据不一致的情况,只有在读和写同时进行的时候,才会出现数据不一致的情况。 

2:写入数据:两种方案

  • 先更新redis缓存,更新数据库;
  • 先更新数据库,再更新redis缓存;

第一种:先更新redis缓存,更新数据库。下图中2节点网络延迟时,线程2的请求拿到的是旧数据,这时候可以在线程1更新数据库成功后,再删除一次redis的缓存。后面的请求就会去数据库查询新的数据,并将数据缓存到redis中

考虑到并发或延迟的情况,在更新数据库成功后删除redis的操作,需要延迟进行,比如500ms,实际时间由具体业务评估。避免线程2查询到了旧数据,还没来得及更新redis,线程1已经将缓存删除,线程2又把旧数据更新到了redis

延迟双删的缺点是延迟删除的这段时间里,请求都是取到的旧数据,但这样保证了数据最终的一致性。

 

第二种:先更新数据库,再更新redis缓存。下图中数据更新数据库成功后,直接删除缓存。线程2查询缓存获取新的数据。

 删除缓存会有一个删除失败的问题:假如节点3删除缓存失败了,那么后面的请求获取到的永远都是旧数据。删除失败后可以引入重试机制,不管是方案一还是方案二都存在删除失败的情况。

在高并发的业务场景下,可以使用 MQ 异步重试机制,重试失败频繁的话,还可以发送告警信息请求人工介入

 

 

posted @   安逺  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示