跳转到内容

与关系库的数据同步

用途:把 MySQL 数据可靠地落到 ES 检索索引里

方式 做法 一致性 风险
应用双写 业务代码里同时写 DB 和 ES 依赖代码正确性 一处失败导致不一致;写放大;无重试则丢
异步事件 DB 事务 → 本地消息表/事务消息 → 消费者写 ES 最终一致,可重放 需要幂等与延迟监控
binlog CDC Canal / Debezium 监听 binlog → 管道 → ES 与业务代码解耦,较完整 需处理乱序、结构变更、全量与增量衔接
定时批量 按更新时间扫描重灌 简单,可兜底 延迟高,删除需额外处理(软删或差集)

实践组合:CDC/事件做主链路 + 定时对账做兜底 + 手动重灌工具做修复。

  1. 乱序覆盖:同一实体的两次变更顺序颠倒,ES 留下旧值。对策:按实体键串行投递;或用 _seq_no/外部版本/业务时间戳拒绝旧版本。
  2. 删除同步:物理删除在 binlog 里是 delete 事件(CDC 可捕获),定时扫描方案则需软删标记或全量差集比对。
  3. 关联字段:搜索索引常需要多表拼接(订单 + 商品 + 客户)。要么在写入侧组装(宽表/物化视图),要么冗余“搜索所需最小字段集”并定义失效链路(关联表变更要触发主文档重建)。
  4. 全量与增量衔接:先全量灌(低峰、副本 0、关 refresh),记录水位(binlog position / 时间戳),再从该位点接增量,最后比对抽样校验。
  • 检索索引按查询视角设计,而不是照搬表结构:一行文档 = 一次搜索要返回的完整卡片。
  • 高频过滤字段用 keyword + filter;全文字段用 text 并配中文分词。
  • 大字段(正文、详情)可只存 DB,ES 存摘要与 ID,避免文档膨胀。
  • 时间序列数据用别名 + 滚动索引(ILM),避免单索引过大。
指标 含义
同步延迟(lag) 事件产生到 ES 可搜的时间,业务承诺的依据
失败与重试数 管道健康度
抽样一致性比对 定期随机抽 ID 比对 DB 与 ES 字段
全量对账差异数 兜底发现漏同步
文档数与主键数差异 粗粒度完整性
误区 修正
应用双写但不处理失败 必须有重试与对账,否则不一致静默累积
把 ES 当权威数据源 它是派生索引,必须可从源重建
CDC 不做乱序保护 后写覆盖先写,出现“数据回退”
索引结构照抄表结构 查询时多轮关联,性能与实现都差
无重建能力 一旦映射不合理或数据错乱就无法恢复
忽视 mapping 变更成本 改类型需 reindex,用别名切换设计好
  • Debezium / Canal 官方文档(Outbox、事件路由)
  • Elasticsearch 官方文档:Reindex API、Aliases
  • Martin Kleppmann《数据密集型应用系统设计》第 3、11 章(派生数据与变更捕获)