当前位置: 首页 > news >正文

Redis 和数据库双写一致性问题如何解决?

Redis 和数据库双写一致性问题如何解决?

在高并发场景下,Redis 常被用作数据库的“前置缓存”以提升读取性能。但当数据需要更新时(写操作),如何保证 Redis 缓存与数据库中的数据最终一致(甚至强一致),就成了经典的“双写一致性”难题。

一、问题根源:先操作缓存还是先操作数据库?

很多同学会本能地想到“先更新数据库,再更新缓存”或“先删除缓存,再更新数据库”。但这两种方式都存在竞态条件风险:

操作顺序可能的问题
先更新缓存,再更新数据库缓存更新成功,数据库更新失败 → 数据不一致
先更新数据库,再更新缓存更新数据库期间,有读请求将旧数据载入缓存 → 脏数据
先删除缓存,再更新数据库删除缓存后、更新数据库前,有读请求将旧数据写回缓存 → 脏数据
先更新数据库,再删除缓存相对安全,但删除缓存失败 → 缓存一直是旧数据

所以业界主流思路是“先更新数据库,再删除缓存”(Cache Aside Pattern)。而你提供的三种方案,正是围绕“如何可靠地删除/更新缓存”展开的。

二、方案详解(优化与完善)

方案一:先更新数据库,再删除缓存 + 重试 + 过期兜底

这是最简单、最直接的做法,核心流程如下:

Redis缓存数据库应用Redis缓存数据库应用依赖缓存过期时间兜底alt[重试仍失败]alt[删除成功][删除失败]1. 更新数据更新成功2. 删除缓存OK异步重试(延迟2秒)重试删除失败

优化点

  • 删除失败后的重试不能无限进行,建议设置最大重试次数(如3次)。
  • 重试间隔可以采用指数退避(2秒、4秒、8秒),避免对 Redis 造成压力。
  • 一定要给缓存设置合理的过期时间(如30分钟),作为最后的“兜底策略”,保证即使所有删除都失败,数据最终也会因过期而重新从 DB 加载。

优点:实现简单,无需引入额外组件。
缺点:重试过程可能短暂影响一致性;高并发下仍有极小概率读到旧数据(在删除缓存之前有读请求)。


方案二:先更新数据库,再发 MQ 消息,由消费者删除/更新缓存

将“删除缓存”这一操作从主线程剥离,通过消息队列(RabbitMQ、RocketMQ、Kafka 等)异步执行。流程如下:

应用发起写请求

更新数据库

更新成功?

发送MQ消息
包含key或数据

返回失败

主线程返回成功

MQ消费者拉取消息

删除/更新Redis缓存

操作成功?

结束

重试队列
或记录失败日志

优化点

  • 消息体建议携带:cache_keyoperation(delete/update)、timestampretry_count
  • 消费者需要保证幂等(多次删除同一 key 无害)。
  • 如果业务需要“更新缓存”而非删除,需谨慎:更新缓存时可能拿到旧值,建议还是以删除为主,让读请求主动加载最新数据。
  • 可以结合 RocketMQ 的事务消息,保证数据库更新和消息发送的原子性(避免数据库成功但消息未发)。

优点:解耦,删除失败不影响主流程;可通过 MQ 的重试机制保证最终一致。
缺点:引入 MQ 增加系统复杂度和延迟。


方案三:监听 MySQL Binlog,异步解析并修改缓存

这是一种“无入侵”的最终一致性方案,利用 Canal、Debezium 等组件伪装成 MySQL slave,解析 binlog 并推送到消息队列或直接更新缓存。

业务层

写操作

产生binlog

解析事件

删除/更新

应用

MySQL

Canal/Debezium

消息队列

缓存同步服务

Redis

时序图(以 Canal 为例)

Redis缓存同步服务MQCanalMySQL应用Redis缓存同步服务MQCanalMySQL应用UPDATE table SET ... WHERE id=?OK推送binlog事件解析成行变更发送变更消息消费消息DELETE key 或 SET新值

优化点

  • binlog 是顺序的,可以保证消息的顺序性,避免并发更新导致的乱序问题。
  • 建议只监听需要的表,减少无用解析。
  • 如果更新操作频繁,可以批量处理(例如每100条 binlog 事件执行一次缓存更新)。
  • 缓存更新策略:删除优于更新,因为更新需要知道新值,而新值从 binlog 中可以直接拿到(Canal 会输出变更后的整行数据),此时可直接执行 SET,但要考虑缓存与数据库数据格式转换问题。

优点:对业务代码零侵入;天然保证数据库变更一定会被处理;适合异构系统同步。
缺点:延迟相对较高(毫秒~秒级);组件多,运维复杂。


三、其他补充方案(横向对比)

除了你提到的三种,实际工程中还有以下常见方案:

3.1 延迟双删(先删缓存,再更新 DB,再删一次)

# 伪代码redis.delete(key)db.update(data)time.sleep(0.1)# 等待可能存在的并发读请求将旧数据写回缓存redis.delete(key)

适用场景:对一致性要求中等,且无法忍受“先更新 DB 再删缓存”导致的短暂不一致(读旧数据)。
注意:sleep 时间需根据业务读耗时估算(通常 100~200ms),过大会影响写性能。

3.2 分布式读写锁(强一致性)

使用 Redisson 等工具对 key 加读写锁:

  • 读请求加读锁,写请求加写锁。
  • 写锁会阻塞所有读锁,保证写期间无读操作,从而避免脏数据。

优点:强一致性。
缺点:性能差,吞吐量下降严重,一般不用于高并发缓存场景。

3.3 对比总结表

方案一致性强度性能影响实现复杂度是否需要额外组件
删除+重试+过期最终一致(弱)
MQ异步删除最终一致MQ
Binlog同步最终一致(顺序保证)低(业务无感)Canal+MQ
延迟双删最终一致(时间窗口更窄)
读写锁强一致极高分布式锁(如Redisson)

四、选型建议

  • 并发量低、一致性要求不苛刻:方案一(删除+重试+过期)足够,代码简单。
  • 要求高可用,不能容忍缓存删除失败:方案二(MQ 异步删除),同时给缓存加过期时间作为兜底。
  • 已有异构数据同步需求,或希望业务无感:方案三(binlog 监听),适合数据中台、CQRS 场景。
  • 对短期不一致零容忍(如金融、库存扣减):考虑分布式锁或直接读数据库,放弃缓存。

五、总结

Redis 与数据库的双写一致性问题没有“银弹”,需要在一致性、性能、复杂度之间做权衡。你提出的三种方案涵盖了从简单到复杂的演进路径:

  1. 同步删除 + 重试 + 过期兜底——入门级,大部分场景够用。
  2. MQ 异步删除——解耦 + 可靠,适合对删除成功率要求高的场景。
  3. Binlog 监听——终极解耦,适合大规模分布式系统。

最后记住一条核心原则:缓存只是加速,数据库才是真相。无论采用何种方案,务必为缓存设置合理的过期时间,给数据一致性留一条最后的退路。


📌附:常见问题

  • Q:先更新数据库再删缓存,如果删除失败怎么办?
    A:重试 + MQ + 过期兜底。
  • Q:为什么不先删缓存再更新数据库?
    A:会导致并发读请求将旧数据写回缓存,产生脏数据。
  • Q:Canal 监听 binlog 会不会有重复消费?
    A:会,需要消费者做幂等设计(如使用唯一事件 ID 或 version 字段)。
http://www.jsqmd.com/news/644674/

相关文章:

  • CDS API 终极指南:Python 连接 Copernicus 气候数据宝库
  • 全面解读 PCA、t-SNE 与 UMAP 三大降维算法
  • 除了Keil和IAR,汽车电子工程师为啥还在用Green Hills MULTI?聊聊它的调试绝活
  • 选购洁净度检测仪必看,高性价比品牌与正规生产厂家汇总 - 品牌推荐大师1
  • 如何永久保存微信聊天记录:WeChatMsg让珍贵对话不再消失
  • 探讨扬州讯灵AI十Agent双引擎优化,其性价比哪家高 - 工业品牌热点
  • 从0x34 RequestDownload看汽车OTA升级:数据下载服务在ECU刷写中的关键作用与安全设计
  • 吵了几个月,Linus终于拍板!Linux正式为AI代码“立法”:允许用AI,但锅必须人背
  • 三分钟上手Midscene:零代码实现全平台UI自动化的终极指南
  • 3大核心技术实现Cursor Pro功能永久免费:终极解决方案指南
  • 【Linux线程】Linux系统多线程(六):<线程同步与互斥>线程同步(上)
  • 3个实战场景:深度解析FinBERT金融情感分析模型的核心应用
  • 非接触超声波破碎仪选购建议:关注实力厂家与知名品牌 - 品牌推荐大师1
  • 跨安全域异构算力整合:GPUStack纳管NPU实战网络隧道架构
  • OSI(Open System Interconnection,开放系统互连)参考模型是国际标准化组织(ISO)制定的网络通信标准框架
  • 生产环境慎用writeback!深入bcache三种缓存模式,附CentOS 7.9实战调优参数
  • 分析电商云仓服务品牌企业费用,哪家价格合理又售后完善 - 工业设备
  • 暗黑破坏神2存档编辑器:免费开源的单机游戏终极修改指南
  • 深入解析 - Linux 文件句柄优化之 ulimit 与 fs.file-max 实战
  • 2026年想提升技术?收藏这份AI大模型学习攻略,小白程序员轻松入门高薪赛道!
  • 总结沃尔沃移动、模块化、特殊用途发电机组推荐哪家 - 工业推荐榜
  • 终极指南:3分钟快速解锁网易云音乐NCM加密文件
  • 探秘细胞因子:趋化因子家族解析
  • Arduino进阶篇(五)-- 高效电源模块设计与实战解析
  • 告别臃肿:用C语言和CivetWeb框架5分钟写一个高性能静态文件服务器
  • 面试官:怎么设计一个直播间实时排行榜?我愣住了,然后彻底搞懂了Redis ZSet
  • 【Agent初认识】我的方法里写了注释,但是LLM生成json根本不看导致参数不匹配怎么办?
  • 5分钟搞定iPhone USB网络共享:Windows下苹果驱动一键安装终极指南
  • 2026年性价比高的移民品牌汇总,分析金征远移民办理加拿大移民靠谱吗 - mypinpai
  • 细聊电线电缆制造企业选择,推荐合作案例多的靠谱厂家 - 工业推荐榜