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 异步重试机制,重试失败频繁的话,还可以发送告警信息请求人工介入
分类:
Redis
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?