Canal 是什么
Canal 是阿里开源的 MySQL 增量订阅组件(Java 实现):它把自己伪装成 MySQL 从库,向主库发送 dump 协议请求,接收主库推送的 binlog 并解析成结构化的事件对象,再提供给客户端或直接投递到消息队列。在 Debezium 与 Flink CDC 普及之前,它是国内使用较多的 CDC 方案。
工作原理与组成
Canal 由 server 与 client 两部分组成:server 负责与 MySQL 建立复制连接、解析日志、维护位点;client 通过 TCP 拉取数据。一个 server 可以配置多个 instance,每个 instance 对应一个 MySQL 实例的订阅。位点需要落盘或存入外部存储,否则重启后会从上次记录的位置重新开始,造成重复或缺口。
基本信息
| 定位 | MySQL binlog 增量订阅与解析组件 |
|---|---|
| 原理 | 模拟从库发送 dump 协议,接收 binlog 并解析 |
| 输出 | Entry / RowChange(行级增删改) |
| 投递 | TCP 客户端拉取,或直接投递 Kafka、RocketMQ 等 |
| 前置 | 源库 binlog_format=ROW,并为 Canal 分配独立 slaveId |
关键概念读法
| 概念 | 含义 | 注意 |
|---|---|---|
| instance | 一个订阅实例,对应一个 MySQL 实例 | 实例越多,server 端资源占用越高 |
| slaveId | 伪装从库时使用的编号 | 不得与真实从库冲突,否则复制报错 |
| Entry | 解析出的日志事件包装对象 | 包含事务头、行变更、DDL 等类型 |
| RowChange | 一条行级增删改事件 | 按行格式日志解析得到 |
| 位点 | 已解析到的 binlog 位置 | 必须持久化,否则重启后重复或漏数 |
典型使用场景
- 业务库变更同步到数仓:把订单、用户表的变更持续投递到消息队列
- 缓存与检索更新:变更事件触发缓存失效或索引重建
- 历史存量同步:配合全量导出工具完成开荒,再用 Canal 追平增量
- 多下游分发:解析一次、投递到消息队列,多个消费方各取所需
- 审计留痕:把变更事件长期保存,支持事后追溯
数据流向
数据流向
# 源端:MySQL 需开启 binlog 且格式为 ROW
MySQL Master
→(dump 协议持续推送 binlog)
Canal Server:解析为 Entry / RowChange,维护位点
→(TCP 拉取或投递消息队列)
Canal Client / Kafka → 下游:数仓 ODS、缓存、检索索引、审计归档Canal 只负责「把变更取出来」,不负责写入目标:落库由客户端或下游消费程序完成,因此幂等、重试与顺序处理仍要在消费侧实现。
位点持久化是 Canal 的生命线:位点丢失后只能重新指定起点,向前会重复消费、向后会造成永久缺口,两者都需要人工核对补数。