Canal 投递 Kafka 是什么
Canal 是模拟 MySQL 从库、解析 binlog 的增量订阅服务。除默认的 TCP 客户端方式外,它支持把解析结果直接投递到消息队列:在 canal.properties 里把 serverMode 设为 kafka、填好 Broker 地址与主题,再用分区哈希参数按主键分区。投递之后业务方消费 Kafka 即可,不必再各自直连 Canal Server,订阅关系与消费位点也统一交给 Kafka 管理。
基本信息
| serverMode | tcp(默认)/ kafka / rocketmq 等,决定投递方式 |
|---|---|
| 连接配置 | kafka.bootstrap.servers 指定 Broker 地址列表 |
| 主题 | canal.mq.topic 指定默认主题,可用动态主题规则按库表拆分 |
| 动态主题 | canal.mq.dynamicTopic 可按库或表维度生成主题名 |
| 分区哈希 | canal.mq.partitionHash 按主键哈希到分区,保持同键有序 |
| 投递语义 | 至少一次投递,下游必须按主键做幂等写入 |
| 实例过滤 | instance 配置中的库表过滤规则决定订阅范围 |
典型使用场景
- MySQL 增量接入 Kafka:业务库变更统一投到消息队列供下游消费
- 多下游分发:一次解析,多个下游各自消费,避免重复订阅源库
- 按主键有序消费:分区哈希保证同一单据的变更顺序不乱
- 多库多表统一接入:用动态主题规则按库表拆主题,权限与消费隔离
- 降低源库压力:下游不再直连 Canal,订阅关系集中在 Kafka
canal.properties 关键项
canal.properties 关键项
# 投递方式与目标 Broker
canal.serverMode = kafka
kafka.bootstrap.servers = 10.0.0.6:9092
# 默认主题与分区数
canal.mq.topic = canal-orders
canal.mq.partitionsNum = 6
# 分区哈希:按主键哈希,保证同一主键落到同一分区
canal.mq.partitionHash = app.orders:id
# 动态主题:按「库.表」拆分主题,便于权限与消费隔离
canal.mq.dynamicTopic = app\..*:app_${table}实例与消费侧核对
实例与消费侧核对
# instance.properties:确认订阅范围与源库连接
# canal.instance.filter.regex = app\..*
# 消费侧核对分区与消息 key,确认同键有序
kafka-console-consumer.sh --bootstrap-server 10.0.0.6:9092 \
--topic canal-orders --from-beginning --max-messages 5 \
--property print.key=true | head关键参数职责
| 参数 | 作用 | 配置错误的后果 |
|---|---|---|
| serverMode | 决定投递到 MQ 还是 TCP 客户端 | 与既有下游协议不符,消费方全部失效 |
| mq.topic | 默认主题名 | 主题不存在时投递失败 |
| dynamicTopic | 按库表动态拆主题 | 规则写错导致所有消息挤进一个主题 |
| partitionHash | 按主键哈希保序 | 配错让同键散落多分区,破坏有序假设 |
| partitionsNum | 分区数量 | 分区过少成为吞吐瓶颈 |
partitionHash 配错会让同一主键散落到多个分区,破坏消费侧的有序假设:下游按主键合并时会先后顺序颠倒,最终值可能是旧的。
Canal 是至少一次投递:位点回退或重投时同一批变更会再次出现,下游必须以主键 upsert 或按位点去重,不能假设「只会来一次」。