Canal 和 MySQL 配置指南

2 篇文章 0 订阅
2 篇文章 0 订阅

1. 环境依赖

在开始配置之前,请确保已安装并配置以下环境:

  • Docker:用于运行 MySQL 和 Canal 的容器化服务。

  • MySQL:确保安装的是支持 binlog 的版本。

  • Canal:阿里巴巴开源的数据库增量订阅和消费组件。

2. MySQL 配置

为了使 Canal 能够正确监听 MySQL 的 binlog 日志,必须进行如下配置:

2.1 开启 binlog

MySQL 使用 binlog 来记录所有的数据库更改。确保 MySQL 配置文件中开启了 binlog,并将日志格式设置为 ROW

在 MySQL 的配置文件 my.cnfmy.ini 中添加或修改以下内容:

# 开启 binlog
log-bin=mysql-bin
​
# 设置 binlog 格式为 ROW 模式
binlog-format=ROW
​
# 为 MySQL 设置 server_id,确保唯一,避免与 Canal 的 slaveId 冲突
server_id=1

2.2 设置 MySQL 用户权限

为 Canal 分配足够的权限以读取 binlog。进入 MySQL 并执行以下命令,为 Canal 用户分配 REPLICATION SLAVEREPLICATION CLIENT 权限:

CREATE USER 'test'@'%' IDENTIFIED BY '123456';
​
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'test'@'%';

确保用户名、密码和主机名与 Canal 的配置一致。

3. Canal 配置

3.1 启动 Canal 容器

通过 Docker 启动 Canal 容器:

docker run --name canal -p 11111:11111 -d canal/canal-server

3.2 复制配置文件

为了自定义配置文件,可以将 Canal 容器内的 instance.properties 文件复制到宿主机,便于修改:

docker cp canal:/home/admin/canal-server/conf/example/instance.properties "D:/docker/canal/conf/"

其中"D:/docker/canal/conf/"是绝对路径,因为我发现如果输入 /d/docker/canal/conf/它其实寻找的是 "C:/d/docker/canal/conf/",所以这里设置绝对路径。

3.3 修改 instance.properties 配置文件

打开复制到本地的 instance.properties 文件,进行如下配置修改:

#################################################
## MySQL 配置
canal.instance.mysql.slaveId=1
​
# MySQL 地址与端口
canal.instance.master.address=172.17.0.3:3306  # MySQL 容器的 IP 地址
​
# MySQL 用户名与密码
canal.instance.dbUsername=test
canal.instance.dbPassword=123456
​
# 数据库表过滤规则
canal.instance.filter.regex=.*\\..*  # 订阅所有表

canal.instance.master.address=172.17.0.3:3306启动容器的时候指定自定义网络那么IP就可以换成容器名,如果默认是bridge网络,那么需要指定IP。

3.4 重新启动 Canal 容器并挂载配置文件

修改完配置文件后,重新启动 Canal 容器,并将本地修改过的配置文件挂载到容器内:

docker run --name canal 
    -p 11111:11111 \
    -v /d/docker/canal/conf/instance.properties:/home/admin/canal-server/conf/example/instance.properties \
    --network bridge 
    -d canal/canal-server

在这里,bridge 是你设置的 Docker 自定义网络,用于确保 Canal 和 MySQL 容器能通过网络相互通信。

4. Canal 集成到项目

4.1 Maven 依赖

将以下依赖添加到项目的 pom.xml 文件中:

<dependency>
  <groupId>com.alibaba.otter</groupId>
  <artifactId>canal.client</artifactId>
  <version>1.1.5</version>
</dependency>
​
<dependency>
  <groupId>com.alibaba.otter</groupId>
  <artifactId>canal.protocol</artifactId>
  <version>1.1.5</version>
</dependency>

4.2 编写 Canal 客户端代码

以下是 Canal 客户端代码的示例,用于连接 Canal 服务并监听 MySQL 数据库的变更:

package com.example.demo;
​
import com.alibaba.otter.canal.client.CanalConnector;
import com.alibaba.otter.canal.client.CanalConnectors;
import com.alibaba.otter.canal.protocol.CanalEntry;
import com.alibaba.otter.canal.protocol.Message;
​
import java.net.InetSocketAddress;
import java.util.List;
​
public class CanalClient {
​
    // Canal 服务地址
    private static final String CANAL_SERVER = "127.0.0.1";
    private static final int CANAL_PORT = 11111;
    private static final String DESTINATION = "example";
​
    public static void main(String[] args) {
        // 连接 Canal 服务
        CanalConnector connector = CanalConnectors.newSingleConnector(
                new InetSocketAddress(CANAL_SERVER, CANAL_PORT),
                DESTINATION, "", "");
​
        connector.connect();
        connector.subscribe(".*\\..*");
        connector.rollback();
​
        while (true) {
            // 获取数据
            Message message = connector.getWithoutAck(100);
            long batchId = message.getId();
            if (batchId != -1) {
                processEntries(message.getEntries());
                connector.ack(batchId);  // 确认处理成功
            }
        }
    }
​
    private static void processEntries(List<CanalEntry.Entry> entries) {
        for (CanalEntry.Entry entry : entries) {
            if (entry.getEntryType() != CanalEntry.EntryType.ROWDATA) {
                continue;
            }
            try {
                CanalEntry.RowChange rowChange = CanalEntry.RowChange.parseFrom(entry.getStoreValue());
                for (CanalEntry.RowData rowData : rowChange.getRowDatasList()) {
                    switch (rowChange.getEventType()) {
                        case INSERT:
                            System.out.println("新增数据: " + rowData.getAfterColumnsList());
                            break;
                        case UPDATE:
                            System.out.println("更新数据: " + rowData.getAfterColumnsList());
                            break;
                        case DELETE:
                            System.out.println("删除数据: " + rowData.getBeforeColumnsList());
                            break;
                        default:
                            break;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

5. 常见问题及排查

5.1 Canal 无法连接 MySQL

  • 问题:出现 Connection refused 错误。

  • 原因:MySQL 容器的 IP 地址或端口未正确配置,或 MySQL 没有正确暴露端口。

  • 解决方案:检查 MySQL 容器的 IP 地址并确认在 instance.properties 中配置正确。

    • 进入到容器里面:docker exec -it canal /bin/bash

    • 找到存放日志的文件夹:cd canal-server/logs/example/

    • 查看最后一百行日志:tail -100 example.log

5.2 MySQL 用户权限问题

  • 问题:出现 SHOW MASTER STATUS 错误。

  • 原因:Canal 用户没有足够的权限读取 binlog。

  • 解决方案:确保 MySQL 中的 Canal 用户拥有 REPLICATION SLAVEREPLICATION CLIENT 权限。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ming__GoGo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值