数据同步与 CDC
微服务拆分后,常需把 MySQL 变更 同步到缓存、ES、数仓或其它服务库。CDC(变更数据捕获) 解析 binlog / WAL,比定时全量扫表延迟低、对源库压力小。概念见 CDC;Canal 见 Canal。
典型链路
MySQL(业务库)
│ binlog ROW
▼
Canal Server / Debezium
▼
Kafka(推荐缓冲)
▼
Spring Boot 消费者 → 更新 Redis / ES / 从库
Canal → Kafka → Spring 消费
MySQL 前提
[mysqld]
log-bin=mysql-bin
binlog-format=ROW
server-id=1Canal 投递 MQ
Canal 支持将 Entry 投递到 Kafka / RocketMQ(见 Canal 服务端配置)。
Spring Kafka 消费示例
@KafkaListener(topics = "canal.order_db", groupId = "cache-sync")
public void onBinlog(String payload) {
CanalMessage msg = parse(payload);
if ("t_order".equals(msg.getTable())) {
if (msg.isDelete()) {
redisTemplate.delete("order:" + msg.getPk());
} else {
redisTemplate.opsForValue().set(
"order:" + msg.getPk(), msg.getAfter(), Duration.ofHours(1));
}
}
}| 要点 | 说明 |
|---|---|
| 幂等 | 同一条 binlog 可能重复投递,用版本号或主键 UPSERT |
| 顺序 | 按表主键分区到同一 Kafka partition |
| 延迟 | 监控消费 lag |
Debezium(Kafka Connect)
多数据库、与 Kafka 生态一体:
Debezium Connector → Kafka Connect → Topic db.schema.table
Spring 侧仍用 @KafkaListener 或 Stream 消费对应 Topic。适合 PG、Mongo 等(见 CDC 工具对比)。
其它同步方式
| 方式 | 工具 / 实现 | 文档 |
|---|---|---|
| 日志 CDC | Canal、Debezium、Maxwell | CDC |
| 批处理同步 | DataX、Sqoop | 离线全量 + 增量 |
| 应用双写 | 不推荐 | 一致性难保证 |
| 本地消息表 | Spring 定时发 MQ | 分布式与数据层 |
与微服务边界
| 做法 | 说明 |
|---|---|
| 推荐 | 单服务写自己的库,CDC 同步读模型(CQRS) |
| 避免 | CDC 回调直接跨服务 Feign 写库(耦合、难幂等) |
| 搜索索引 | MySQL → Canal → Kafka → 写 ES |
| 缓存失效 | DELETE/UPDATE 事件删 Redis key |
Spring Cloud 中的位置
CDC 消费者通常是 独立 Sync 服务(Spring Boot),注册到 Nacos,与业务服务解耦;不要求 Stream,但可与 消息驱动 统一 Binder。