1022 字
约 3 分钟
10
S11-A03 · MySQL → ES / 缓存一致性

适用读者:要做"数据库 + 搜索/缓存"双写的人。
前置:S11-J05。
覆盖旧文:2686(141) 2690(141) 2666(84) 1732(79) = 445 点。
覆盖扩展:E-S11-009(三方案对比)。
上一篇:S11-A02 · 部署与迁移:Docker 跑 MySQL、Flyway
下一篇:S11-X01 · 八股速查。


1. 一句话结论

"数据库 + 另一个存储"的一致性只有三种路线:双写、订阅 binlog、定时对账。它们的差别在"延迟、侵入性、可靠性"。

方案 延迟 侵入性 可靠性
双写(应用里同时写两边) 低 高(业务代码要管) 差(一边失败就脏)
binlog 订阅 / CDC 中(秒级) 低(对应用透明) 好(可回溯)
定时对账 高(分钟+) 低 兜底用,不做主路径

2. 双写为什么不推荐(E-S11-009)

① 写 MySQL 成功 → ② 写 ES 失败 → 数据不一致
① 写 MySQL 失败 → ② 写 ES 成功 → 脏数据
补救 效果
加重试 只能缓解,最终一致仍可能失败
加事务消息 引入 MQ,复杂度上升
失败落表 + 补偿任务 可行,但等于自己写了个 CDC

判据:"能接受双写的不一致窗口吗?" 不能 → 别用双写做主路径。


3. binlog 订阅(推荐)

组件 说明
Canal / Debezium / Maxwell 伪装成从库读取 binlog
消息队列 缓冲与解耦
消费端 写 ES / 更新业务

前提:binlog_format=ROW(必须)、binlog_row_image=FULL(推荐)、有权限。

优势:应用无侵入、可回溯、断点续传。

代价:多一套组件、需要监控消费延迟。


4. 缓存一致性:先删缓存还是先更库(A-1732)

方案 问题
先更库、后删缓存 并发下仍可能读到旧值(窗口小)
先删缓存、后更库 窗口更大(容易读到旧值)
延迟双删 更库前后各删一次,缓解
订阅 binlog 删缓存 最彻底(与 §3 同源)

判据:"缓存里的旧值能存在多久?" 要求"秒级以下" → binlog 驱动;容忍几十毫秒 → 延迟双删够用。

"cache-aside 的经典竞态":读线程先读库、再写缓存;写线程中途删缓存 → 缓存里留下旧值。根本解法只有"让失效消息来自数据变更本身"(binlog)。


5. 迁移与验收

阶段 动作
双写期 主写 MySQL,旁路写 ES(观察差异)
切换期 读切 ES(灰度 1%→100%)
收口 关掉旁路双写,改 binlog 订阅
对账 定时全量/增量比对(兜底)

验收指标:同步延迟 P99、差异条数、消费积压。


6. 五个误区

误区 真相
"双写最简单" 不一致窗口最大
"binlog 订阅没有延迟" 秒级延迟仍存在
"缓存删除顺序决定一切" 竞态窗口存在,最终要靠数据变更驱动
"对账能做主路径" 只能兜底
"ES 能替代数据库" 不是事务型存储

7. 自检(架构师版)

  1. 三种同步方案的延迟/侵入性/可靠性对比?
  2. 双写为什么"失败即脏"?
  3. binlog 订阅的三个前提?
  4. 缓存一致性的根本解法是什么?
  5. 迁移的四阶段与验收指标?

8. 下一篇

S11-X01 · MySQL 八股速查

最后一篇是附录索引:83 道 MySQL 八股压成"题 → 一句话答案 → 正文位置"。


本篇属于系列《S11 · 数据库与 SQL》。旧文来源:A-2686/2690/2666/1732;扩展点 E-S11-009。

S11-A03 · MySQL → ES / 缓存一致性
https://www.clxhxhhr.top/posts/5341/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。