Loading...

文章背景图

Canal:超详细部署与使用教程

2026-10-27
0
- 字
- 分钟
|

Canal:超详细部署与使用教程

Canal(译意为「水道/管道/沟渠」)是阿里巴巴开源的 MySQL 数据库增量日志解析组件,基于 MySQL binlog 实现增量数据订阅与消费,可用于数据库镜像、实时备份、索引构建、缓存刷新、异构数据同步等场景。

所属公司 GitHub 仓库 官方文档/官网 开源协议 Star 数 最新版本(截至 2026-10-27) 主要语言
阿里巴巴(开源) github.com/alibaba/canal 官方文档均在 GitHub Wiki:github.com/alibaba/canal/wiki Apache-2.0 约 30k canal-1.1.8 Java

目录


一、项目概述

1.1 项目定位

早期阿里巴巴因杭州与美国双机房部署,需要跨机房数据同步,最初通过业务 trigger 获取增量变更;2010 年起改为直接解析数据库日志获取增量,由此衍生出大量数据库增量订阅与消费业务,Canal 即源于此。Canal 本身是一个MySQL binlog 增量订阅&消费组件:它模拟 MySQL slave 的交互协议,伪装成 slave 向 master 发送 dump 协议,接收并解析 binary log,再以 protobuf 3.0 协议提供给下游 client 消费。

当前 Canal 支持的源端 MySQL 版本:5.1.x、5.5.x、5.6.x、5.7.x、8.0.x(官方 README 说明)。

1.2 核心功能

  • binlog 增量订阅与解析:伪装成 MySQL slave,拉取并解析 ROW 模式 binlog,还原 INSERT/UPDATE/DELETE 事件。
  • 增量订阅消费的典型业务:数据库镜像、数据库实时备份、索引构建与实时维护(拆分异构索引、倒排索引)、业务 cache 刷新、带业务逻辑的增量数据处理。
  • client-server 模式:server 与 client 之间使用 protobuf 3.0 协议,client 可用多种语言实现(官方提供 Java 客户端,社区有 C# CanalSharp、Go canal-go、PHP、Python、Rust、Node.js 客户端)。
  • 消息投递集成:原生支持将变更投递到 Kafka / RocketMQ(1.1.x 起),借助 MQ 的多语言与削峰能力消费。
  • 阿里云 RDS 订阅:原生支持阿里云 RDS for MySQL 的 binlog 订阅(含自动主备切换、OSS binlog 离线解析)。
  • Canal Admin(1.1.4 起):引入 canal-admin 工程,提供 WebUI 动态管理能力——在线配置、Instance 任务管理、日志白屏运维。
  • Prometheus 监控:1.1.x 起原生支持 Prometheus 指标暴露。
  • Docker 镜像:1.1.x 起官方提供 Docker 镜像。

1.3 工作原理

Canal 的工作原理建立在 MySQL 主备复制原理之上:

  • MySQL master 将数据变更写入二进制日志(binary log,记录叫做 binary log events,可通过 show binlog events 查看);
  • MySQL slave 将 master 的 binary log events 拷贝到自己的中继日志(relay log);
  • MySQL slave 重放 relay log 中的事件,反映到自己的数据上。

Canal 做的事:

  1. 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave,向 MySQL master 发送 dump 协议;
  2. MySQL master 收到 dump 请求后,开始推送 binary log 给 slave(即 canal);
  3. Canal 解析 binary log 对象(原始为 byte 流),转换为统一的消息结构供 client 消费。

Canal Logo

整体组件结构:Canal 部署包中 instance 是核心单元,每个 instance 对应一个数据源订阅任务(默认 example);server 负责与 client 的交互与调度;parse 负责 binlog 解析;sink/store 负责事件投递与缓冲。


二、环境要求

项目 要求
操作系统 Linux 推荐(生产);macOS / Windows 可用于开发测试
JDK JDK 8 及以上(Canal 为 Java 应用)
源端 MySQL 5.1.x / 5.5.x / 5.6.x / 5.7.x / 8.0.x;必须开启 binlog,且 binlog-format=ROW
MySQL 账号 需有 REPLICATION SLAVE、REPLICATION CLIENT 权限
网络 Canal 机器需能访问 MySQL 的 3306;client 需能访问 Canal Server(默认 11111 端口)
中间件(可选) 集群模式需要 ZooKeeper;投递 Kafka/RocketMQ 需对应 MQ 集群;Canal Admin 需要 MySQL(存储元数据)
硬件 单实例测试 1C2G 可跑;生产按 binlog 流量评估,建议 2C4G 起步

关键前提:源端 MySQL 的 my.cnf 必须配置 log-bin=mysql-bin、binlog-format=ROW、server_id=1(该 server_id 不能与 canal 的 slaveId 重复)。


三、部署方式

下面给出:压缩包部署(标准方式)→ Docker 部署 → Canal Admin WebUI 管理端部署 → Kafka/RocketMQ 投递对接。

3.1 方式一:压缩包部署(标准方式)

步骤 0:准备源端 MySQL

修改 my.cnf:

[mysqld]
log-bin=mysql-bin          # 开启 binlog
binlog-format=ROW          # 选择 ROW 模式
server_id=1                # 主从复制需要的 server_id,勿与 canal slaveId 重复

重启 MySQL 后,创建并授权 canal 账号(官方 Wiki QuickStart):

CREATE USER canal IDENTIFIED BY 'canal';
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%';
FLUSH PRIVILEGES;

若使用阿里云 RDS for MySQL,默认已开启 binlog 且账号默认具备 binlog dump 权限,可跳过此步。

步骤 1:下载解压

从 Release 页下载:github.com/alibaba/canal/releases,最新版本 canal-1.1.8,产物为 canal.deployer-1.1.8.tar.gz:

mkdir -p /opt/canal
cd /opt/canal
wget https://github.com/alibaba/canal/releases/download/canal-1.1.8/canal.deployer-1.1.8.tar.gz
tar zxvf canal.deployer-1.1.8.tar.gz

解压后目录结构:

bin/        # 启动/停止脚本
conf/       # 配置(canal.properties 全局配置 + example/instance.properties 实例配置)
lib/        # 依赖
logs/       # 日志

步骤 2:修改实例配置

编辑 conf/example/instance.properties(官方 QuickStart 给出的最小配置项):

## mysql serverId
canal.instance.mysql.slaveId = 1234

# position info:改成自己的数据库信息
canal.instance.master.address = 127.0.0.1:3306
canal.instance.master.journal.name =
canal.instance.master.position =
canal.instance.master.timestamp =

# username/password:改成自己的数据库信息
canal.instance.dbUsername = canal
canal.instance.dbPassword = canal
canal.instance.defaultDatabaseName =
canal.instance.connectionCharset = UTF-8

# table regex:只订阅指定库表(默认 .*\..* 即全部)
canal.instance.filter.regex = .*\..*

说明:canal.instance.connectionCharset 对应 Java 编码类型(UTF-8 / GBK / ISO-8859-1);单 CPU 机器需将 canal.instance.parser.parallel 设为 false。

全局配置 conf/canal.properties 中常用项:

配置项 说明 默认值
canal.destinations 本 server 包含的 instance 列表 example
canal.port server 提供给 client 的端口 11111
canal.zkServers 集群模式 ZooKeeper 地址(单机留空) 空
canal.serverMode 投递模式:tcp / kafka / rocketMQ / rabbitMQ tcp

步骤 3:启动与停止

sh bin/startup.sh
# 停止
sh bin/stop.sh

步骤 4:验证启动成功

# 查看 server 日志,出现以下内容即成功
tail -f logs/canal/canal.log
# 期望输出:
# INFO  com.alibaba.otter.canal.deployer.CanalLauncher - ## the canal server is running now ......

# 查看 instance 日志
tail -f logs/example/example.log
# 期望输出:
# INFO  c.a.otter.canal.instance.spring.CanalInstanceWithSpring - start successful....

3.2 方式二:Docker 部署

官方 Wiki 提供 Docker QuickStart。示例:

docker run -d --name canal \
  -p 11111:11111 \
  -v /opt/canal/conf:/home/admin/canal/conf \
  canal/canal-server:v1.1.8

镜像 tag 与 release 对应(以官方 Wiki「Docker QuickStart」为准);生产建议挂载 conf 目录替换配置。

3.3 方式三:Canal Admin WebUI 管理端(1.1.4+,推荐生产)

Canal Admin 是面向 WebUI 的动态管理端,可在线管理集群、Server、Instance 与日志。

步骤 1:部署 canal-admin

从 Release 页下载 canal.admin-1.1.8.tar.gz,其元数据需要 MySQL(先执行官方 Wiki 给出的 canal_admin.sql 建表脚本),然后配置 conf/application.yml 中的数据源后启动:

sh bin/startup.sh
# 默认 Web 端口 8089(以官方 Wiki Canal-Admin-Guide 为准)

步骤 2:配置被管的 canal server

被管的 canal server 在 canal.properties 中接入 admin:

canal.admin.manager = 127.0.0.1:8089
canal.admin.port = 11110
canal.admin.user = admin
canal.admin.passwd = 4ACFE3202A5FF5CF467898FC58AAB1D61502944

步骤 3:WebUI 操作

浏览器登录 admin 后,可在「Canal Server → 集群管理」中新建集群(填写集群名称 + ZooKeeper 地址),在「Server 管理 / Instance 管理」中动态创建与启停订阅任务。

Canal Admin WebUI 新建集群界面(官方 Wiki)

3.4 方式四:对接 Kafka / RocketMQ 投递

修改 canal.properties 切换投递模式:

canal.serverMode = rocketMQ     # 或 kafka
canal.mq.servers = 127.0.0.1:9876

并在 instance.properties 指定目标 topic:

canal.mq.topic = example_topic
# 按库表路由时可指定 partition 规则(以官方 Wiki Canal-Kafka-RocketMQ-QuickStart 为准)

重启后,binlog 变更事件将直接投递到 MQ,下游消费方只需订阅 MQ,无需再直连 Canal Server。

3.5 验证部署成功(通用)

  1. logs/canal/canal.log 出现 the canal server is running now;
  2. logs/example/example.log 出现 start successful;
  3. 在源端 MySQL 对订阅表执行 INSERT,client 端(见 4.1)能收到对应变更消息。

四、使用方法

4.1 基础用法:Java 客户端消费

官方 Wiki 提供 client 示例(CanalConnector API):

import com.alibaba.otter.canal.client.CanalConnector;
import com.alibaba.otter.canal.client.CanalConnectors;
import com.alibaba.otter.canal.protocol.Message;
import com.alibaba.otter.canal.protocol.CanalEntry;

import java.net.InetSocketAddress;

public class CanalClientDemo {
    public static void main(String[] args) {
        // 连接 canal server,订阅 example 实例的全部表
        CanalConnector connector = CanalConnectors.newSingleConnector(
                new InetSocketAddress("127.0.0.1", 11111),
                "example", "", "");
        connector.connect();
        connector.subscribe(".*\\..*");
        connector.rollback();

        while (true) {
            Message message = connector.getWithoutAck(100); // 拉取 100 条
            long batchId = message.getId();
            if (batchId == -1 || message.getEntries().isEmpty()) {
                try { Thread.sleep(1000); } catch (InterruptedException ignored) {}
                continue;
            }
            for (CanalEntry.Entry entry : message.getEntries()) {
                if (entry.getEntryType() == CanalEntry.EntryType.ROWDATA) {
                    // 解析 RowChange 事件,按需处理 INSERT/UPDATE/DELETE
                    System.out.println(entry.toString());
                }
            }
            connector.ack(batchId); // 确认消费
        }
    }
}

引入依赖(官方 README):

<dependency>
    <groupId>com.alibaba.otter</groupId>
    <artifactId>canal.client</artifactId>
    <version>1.1.8</version>
</dependency>

4.2 常用命令/操作

# 启动 / 停止 / 重启
sh bin/startup.sh
sh bin/stop.sh

# 查看日志
tail -f logs/canal/canal.log        # server 主日志
tail -f logs/example/example.log    # example 实例日志

# 源端确认 binlog 状态
SHOW VARIABLES LIKE 'log_bin';
SHOW VARIABLES LIKE 'binlog_format';
SHOW MASTER STATUS;

4.3 进阶功能

  • 多实例订阅:在 canal.destinations 中配置多个 instance(如 example,order_db),每个实例独立配置 conf/<dest>/instance.properties。
  • 表/库过滤:canal.instance.filter.regex 用正则精确订阅(如 order_db\.\*),减少无用事件。
  • 集群高可用:配合 ZooKeeper,同一 destination 部署多节点,同一时刻只有一个节点工作,宕机自动切换(官方 Wiki AdminGuide)。
  • Prometheus 监控:1.1.x 原生支持,暴露指标供 Prometheus 采集(官方 Wiki「Prometheus QuickStart」)。
  • 多语言客户端:Go(canal-go)、C#(CanalSharp)、Python、PHP、Rust、Node.js 客户端均可直接 tcp 模式消费。

4.4 适用场景

  • MySQL 到异构存储的实时同步(ES 索引、Redis 缓存、数仓);
  • 数据库实时备份/灾备;
  • 业务 cache 刷新(订单变更后自动清缓存);
  • 拆库拆表后的数据归并;
  • 数据审计与变更事件驱动(CDC,Change Data Capture)。

五、常见问题排查(FAQ)

Q1:instance 日志报 ERROR: You are not using binary logging 或 could not find first log file - 原因:源端 MySQL 未开启 binlog,或 binlog-format 不是 ROW。 - 解决:按「环境要求」修改 my.cnf(log-bin=mysql-bin + binlog-format=ROW)并重启 MySQL。

Q2:报 Access denied; you need (at least one of) the REPLICATION SLAVE privilege(s) for this operation - 原因:canal 账号权限不足。 - 解决:GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%'; FLUSH PRIVILEGES;

Q3:启动后 example.log 一直卡在 subscribe ...,无数据 - 原因:① 源端没有写入;② canal.instance.filter.regex 过滤掉了目标表;③ position 从很久以前的位点开始,正在追 binlog。 - 解决:先在源端对订阅表 INSERT 测试;确认 regex 正确(默认 .*\..*);观察日志追位点进度。

Q4:client 收不到数据,但 getWithoutAck 返回空 - 原因:尚未 subscribe,或未先 rollback 重置;批量拉取参数过小。 - 解决:确认调用了 connector.subscribe(".*\\..*");参考 4.1 示例先 rollback() 再循环拉取。

Q5:canal.instance.mysql.slaveId 与 MySQL server_id 冲突报错 - 原因:canal 伪装的 slaveId 与主库或已有 slave 重复。 - 解决:把 canal.instance.mysql.slaveId 改成未占用的值(如 1234)。

Q6:MySQL 8.0 连接报认证插件错误(caching_sha2_password) - 原因:MySQL 8 默认认证插件,老版本 canal 驱动不支持。 - 解决:升级到 1.1.5+ 版本;或对 canal 账号 ALTER USER 'canal'@'%' IDENTIFIED WITH mysql_native_password BY 'canal';。

Q7:单 CPU 机器解析卡住或报错 - 解决:官方 Wiki 明确要求单 CPU 机器将 canal.instance.parser.parallel 设为 false。


六、部署注意事项与最佳实践

  1. 生产用 ROW 模式:STATEMENT 模式无法可靠还原行变更,一律 ROW;大表 DDL 会产生大事务,评估 binlog 体积。
  2. slaveId 唯一:canal 模拟 slave,slaveId 不能与源库 server_id 及其他 slave 重复。
  3. 不要用 root 直连:专用 canal 账号,最小权限(SELECT + REPLICATION 权限)。
  4. 过滤精准化:用 canal.instance.filter.regex 只订阅需要的库表,减少解析与网络开销。
  5. 消费必须 ack:client 处理完务必 ack(batchId),否则会重复拉取;处理失败时 rollback 重试。
  6. 集群必配 ZooKeeper:单节点 deployer 挂了就停更,生产用 ZK 做主备切换。
  7. 大数据量走 MQ:tcp 直连适合小流量;流量大、下游多,用 RocketMQ/Kafka 模式解耦。
  8. 监控纳入 Prometheus:1.1.x 原生支持,关注解析延迟与积压。

七、参考资料

  • GitHub 仓库:https://github.com/alibaba/canal
  • Wiki 首页:https://github.com/alibaba/canal/wiki/Home
  • QuickStart:https://github.com/alibaba/canal/wiki/QuickStart
  • Docker QuickStart:https://github.com/alibaba/canal/wiki/Docker-QuickStart
  • Canal Kafka/RocketMQ QuickStart:https://github.com/alibaba/canal/wiki/Canal-Kafka-RocketMQ-QuickStart
  • Canal Admin 指南:https://github.com/alibaba/canal/wiki/Canal-Admin-Guide
  • Prometheus 监控:https://github.com/alibaba/canal/wiki/Prometheus-QuickStart
  • 阿里云 RDS 订阅:https://github.com/alibaba/canal/wiki/aliyun-RDS-QuickStart
  • Client API:https://github.com/alibaba/canal/wiki/ClientAPI
  • FAQ:https://github.com/alibaba/canal/wiki/FAQ
  • Release 下载:https://github.com/alibaba/canal/releases
评论交流

文章目录