大厂ES搜索引擎主流做法:基于 Binlog 的异步同步(CDC - Change Data Capture)

不会在业务代码里写 es.save(),那太 Low 了,而且会把业务逻辑拖死。

1. 核心架构图解

大厂的做法是把“写 MySQL”和“同步 ES”彻底拆开,互不干扰。

流程如下:

  1. 业务代码:只管往 MySQL 写数据,写完就结束,完全不知道 ES 的存在。
  2. MySQL:自动生成 Binlog(操作日志)。
  3. 中间件(如阿里的 Canal):把自己伪装成 MySQL 的从库(Slave),监听主库的 Binlog。
  4. 消息队列(Kafka/RocketMQ):Canal 解析到数据变化后,投递到 MQ。
  5. 同步服务(你的消费者代码):监听 MQ,拿到数据,组装,写入 ES。

2. 为什么这是大厂主流?

  • 解耦: 你的业务代码(下单、注册)不需要依赖 ES。万一 ES 挂了,或者同步代码报错了,不影响用户下单。
  • 削峰: 双 11 流量来了,MySQL 扛住了就行,同步 ES 慢个 1-2 秒完全没问题(最终一致性)。
  • 零侵入: 就算以后不加 ES 了,要换成 Solr 或者别的,业务代码一行都不用改,改同步服务就行。

3. 关键点总结(防坑指南)

  1. 幂等性(Idempotency):
    • 千万记得: ES 的文档 ID (_id) 必须等于 MySQL 的主键 ID。
    • 这样一来,如果 MQ 重发了消息(比如网络抖动发了两次),ES 执行两次 PUT /users/_doc/1001,结果是一样的,不会出现重复数据。
  2. 顺序性(Ordering):
    • 如果你先改了名字叫 “A”,毫秒级后又改名叫 “B”。如果 MQ 乱序了,先处理了 “B” 后处理了 “A”,那数据就错了。
    • 大厂解法: Kafka 的 Partition Key 设置为 userId。这样同一个用户的变更永远在同一个队列里,严格有序。
  3. 回表(可选):
    • Binlog 里只有单表数据。如果你 ES 里存的是宽表(比如包含 User 信息 + 他的 Department 名字),光靠 User 表的 Binlog 不够。
    • 这时候 syncToEs 方法里,拿到 userId 后,可能需要再去调一下 MySQL 或者 Redis,把完整的宽表数据拼凑出来,再写入 ES。

新颖做法: flink cdc
在这里插入图片描述

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐