大厂ES搜索引擎主流做法:基于 Binlog 的异步同步(CDC - Change Data Capture)
幂等性(Idempotency):ES 的文档 ID (_id) 必须等于 MySQL 的主键 ID。这样一来,如果 MQ 重发了消息(比如网络抖动发了两次),ES 执行两次,结果是一样的,不会出现重复数据。如果你先改了名字叫 “A”,毫秒级后又改名叫 “B”。如果 MQ 乱序了,先处理了 “B” 后处理了 “A”,那数据就错了。Kafka 的 Partition Key 设置为userId。这样
·
大厂ES搜索引擎主流做法:基于 Binlog 的异步同步(CDC - Change Data Capture)
不会在业务代码里写 es.save(),那太 Low 了,而且会把业务逻辑拖死。
1. 核心架构图解
大厂的做法是把“写 MySQL”和“同步 ES”彻底拆开,互不干扰。
流程如下:
- 业务代码:只管往 MySQL 写数据,写完就结束,完全不知道 ES 的存在。
- MySQL:自动生成
Binlog(操作日志)。 - 中间件(如阿里的 Canal):把自己伪装成 MySQL 的从库(Slave),监听主库的 Binlog。
- 消息队列(Kafka/RocketMQ):Canal 解析到数据变化后,投递到 MQ。
- 同步服务(你的消费者代码):监听 MQ,拿到数据,组装,写入 ES。
2. 为什么这是大厂主流?
- 解耦: 你的业务代码(下单、注册)不需要依赖 ES。万一 ES 挂了,或者同步代码报错了,不影响用户下单。
- 削峰: 双 11 流量来了,MySQL 扛住了就行,同步 ES 慢个 1-2 秒完全没问题(最终一致性)。
- 零侵入: 就算以后不加 ES 了,要换成 Solr 或者别的,业务代码一行都不用改,改同步服务就行。
3. 关键点总结(防坑指南)
- 幂等性(Idempotency):
- 千万记得: ES 的文档 ID (
_id) 必须等于 MySQL 的主键 ID。 - 这样一来,如果 MQ 重发了消息(比如网络抖动发了两次),ES 执行两次
PUT /users/_doc/1001,结果是一样的,不会出现重复数据。
- 千万记得: ES 的文档 ID (
- 顺序性(Ordering):
- 如果你先改了名字叫 “A”,毫秒级后又改名叫 “B”。如果 MQ 乱序了,先处理了 “B” 后处理了 “A”,那数据就错了。
- 大厂解法: Kafka 的 Partition Key 设置为
userId。这样同一个用户的变更永远在同一个队列里,严格有序。
- 回表(可选):
- Binlog 里只有单表数据。如果你 ES 里存的是宽表(比如包含 User 信息 + 他的 Department 名字),光靠 User 表的 Binlog 不够。
- 这时候
syncToEs方法里,拿到 userId 后,可能需要再去调一下 MySQL 或者 Redis,把完整的宽表数据拼凑出来,再写入 ES。
新颖做法: flink cdc
更多推荐
所有评论(0)