基于canal和kafka同步,实现binlog同步mysql

在这里插入图片描述

前言

最近业务需要监听mysql的binlog日志,于是就看了下canal,下面记录踩到的坑。

简介

在这里插入图片描述
canal [kə’næl],译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费

早期阿里巴巴因为杭州和美国双机房部署,存在跨机房同步的业务需求,实现方式主要是基于业务 trigger 获取增量变更。从 2010 年开始,业务逐步尝试数据库日志解析获取增量变更进行同步,由此衍生出了大量的数据库增量订阅和消费业务。

基于日志增量订阅和消费的业务包括

  • 数据库镜像
  • 数据库实时备份
  • 索引构建和实时维护(拆分异构索引、倒排索引等)
  • 业务 cache 刷新
  • 带业务逻辑的增量数据处理

Canal 的工作原理

在这里插入图片描述

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

canal 工作原理

  • canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送dump 协议
  • MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal )
  • canal 解析 binary log 对象(原始为 byte 流)

搭建环境

中间件版本
mysql5.7
kafka2.13-2.4.0
zookeeper3.6.0
canal1.1.4

安装mysql

这个我用的docker-compose安装,需要安装的可以参考我之前的博客
docker搭建mysql主从搭建及Sharding-Jdbc读写分离,这篇博客我详细讲解了如何搭建mysql主从。但是要注意的是,binlog format需要设置为row模式。

├── docker-compose.yml
├── master
│   ├── Dockerfile
│   └── my.cnf
├── slave
│   ├── Dockerfile
│   └── my.cnf
└── slave2
    ├── Dockerfile
    └── my.cnf

这里需要改下my.cnf文件

binlog_format=mixed

启动成功,输入SHOW VARIABLES LIKE '%bin%'; 对照下下面两行。

在这里插入图片描述

安装Zookeeper及Kafka

Canal和Kafka集群都依赖于Zookeeper做服务协调,为了方便管理,一般会独立部署Zookeeper服务或者Zookeeper集群。这里使用docker-compose脚本部署,脚本如下:

version: '2'
services:
  zookeeper:
    image: wurstmeister/zookeeper   ## 镜像
    ports:
      - "2181:2181"                 ## 对外暴露的端口号
  kafka:
    image: wurstmeister/kafka       ## 镜像
    volumes:
        - /etc/localtime:/etc/localtime ## 挂载位置(kafka镜像和宿主机器之间时间保持一直)
    ports:
      - "9092:9092"
    environment:
      KAFKA_ADVERTISED_HOST_NAME: 192.168.56.119   ## 修改:宿主机IP
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181       ## 卡夫卡运行是基于zookeeper的
  kafka-manager:
    image: sheepkiller/kafka-manager                ## 镜像:开源的web管理kafka集群的界面
    environment:
        ZK_HOSTS:                    ## 修改:宿主机IP
    ports:
      - "9000:9000"

docker-compose up -d
Starting kafka_kafka_1         ... done
Starting kafka_zookeeper_1     ... done
Starting kafka_kafka-manager_1 ... done

搭建canal

终于到了主角登场,这里选用Canal的v1.1.4稳定发布版,只需要下载deployer模块:

mkdir /data/canal
cd /data/canal
# 这里注意一点,Github在国内被墙,下载速度极慢,可以先用其他下载工具下载完再上传到服务器中
wget https://github.com/alibaba/canal/releases/download/canal-1.1.4/canal.deployer-1.1.4.tar.gz
tar -zxvf canal.deployer-1.1.4.tar.gz

解压后的目录如下:

- bin   # 运维脚本
- conf  # 配置文件
  canal_local.properties  # canal本地配置,一般不需要动
  canal.properties        # canal服务配置
  logback.xml             # logback日志配置
  metrics                 # 度量统计配置
  spring                  # spring-实例配置,主要和binlog位置计算、一些策略配置相关,可以在canal.properties选用其中的任意一个配置文件
  example                 # 实例配置文件夹,一般认为单个数据库对应一个独立的实例配置文件夹
    instance.properties   # 实例配置,一般指单个数据库的配置
- lib   # 服务依赖包
- logs  # 日志文件输出目录

在开发和测试环境建议把logback.xml的日志级别修改为DEBUG方便定位问题。这里需要关注canal.properties和instance.properties两个配置文件。canal.properties文件中,需要修改:

  • 去掉canal.instance.parser.parallelThreadSize = 16这个配置项的注释,也就是启用此配置项,和实例解析器的线程数相关,不配置会表现为阻塞或者不进行解析。
  • canal.serverMode配置项指定为kafka,可选值有tcp、kafka和rocketmq(master分支或者最新的的v1.1.5-alpha-1版本,可以选用rabbitmq),默认是kafka。
  • canal.mq.servers配置需要指定为Kafka服务或者集群Broker的地址,这里配置为127.0.0.1:9092。

canal.mq.servers在不同的canal.serverMode有不同的意义。kafka模式下,指Kafka服务或者集群Broker的地址,也就是bootstrap.servers rocketmq模式下,指NameServer列表 rabbitmq模式下,指RabbitMQ服务的Host和Port

其他配置项可以参考下面两个官方Wiki的链接:

  • Canal-Kafka-RocketMQ-QuickStart
  • AdminGuide

instance.properties一般指一个数据库实例的配置,Canal架构支持一个Canal服务实例,处理多个数据库实例的binlog异步解析。instance.properties需要修改的配置项主要包括:

  • canal.instance.mysql.slaveId需要配置一个和Master节点的服务ID完全不同的值,这里笔者配置为654321。

  • 配置数据源实例,包括地址、用户、密码和目标数据库:

    • canal.instance.master.address,这里指定为127.0.0.1:33065。
    • canal.instance.dbUsername,这里指定为root。
    • canal.instance.dbPassword,这里指定为root。
    • 新增canal.instance.defaultDatabaseName,这里指定为test(需要在MySQL中建立一个test数据库,见前面的流程)。
  • Kafka相关配置,这里暂时使用静态topic和单个partition:

    • canal.mq.topic,这里指定为test,也就是解析完的binlog结构化数据会发送到Kafka的命名为test的topic中。
    • canal.mq.partition,这里指定为0。

配置工作做好之后,可以启动Canal服务:

sh /data/canal/bin/startup.sh
# 查看服务日志
tail -100f /data/canal/logs/canal/canal
# 查看实例日志  -- 一般情况下,关注实例日志即可
tail -100f /data/canal/logs/example/example.log

启动正常后,见实例日志如下:
在这里插入图片描述
在test数据库创建一个订单表,并且执行几个简单的DML:


use `test`;

CREATE TABLE `order`
(
    id          BIGINT UNIQUE PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
    order_id    VARCHAR(64)    NOT NULL COMMENT '订单ID',
    amount      DECIMAL(10, 2) NOT NULL DEFAULT 0 COMMENT '订单金额',
    create_time DATETIME       NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    UNIQUE uniq_order_id (`order_id`)
) COMMENT '订单表';

INSERT INTO `order`(order_id, amount) VALUES ('10086', 999);
UPDATE `order` SET amount = 10087 WHERE order_id = '10086';
DELETE  FROM `order` WHERE order_id = '10086';

这个时候,进入容器的kafka-console-consumer或者Kafka Tools查看test这个topic的数据

docker exec -it be206dc159e6 /bin/bash

sh ./bin/kafka-console-consumer.sh --bootstrap-server 127.0.0.1:9092 --from-beginning --topic test

在这里插入图片描述

可见Kafka的名为test的topic已经写入了对应的结构化binlog事件数据,可以编写消费者监听Kafka对应的topic然后对获取到的数据进行后续处理。

搭建canal

拉取代码 https://github.com/alibaba/canal/releases/tag/canal-1.1.4

在这里插入图片描述

  • 配置application.yml文件
server:
  port: 8081
logging:
  level:
    org.springframework: INFO
    com.alibaba.otter.canal.client.adapter.hbase: DEBUG
    com.alibaba.otter.canal.client.adapter.es: DEBUG
    com.alibaba.otter.canal.client.adapter.rdb: DEBUG
spring:
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
    default-property-inclusion: non_null

canal.conf:
  mqServers: 192.168.56.119:9092 #or rocketmq
  flatMessage: true
  batchSize: 500
  syncBatchSize: 1000
  retries: 0
  timeout:
  accessKey:
  secretKey:
  mode: kafka # tcp kafka rocketMQ
  srcDataSources:
    demoSrc:
      url: jdbc:mysql://192.168.56.119:33065/test?useUnicode=true
      username: root
      password: root
  canalAdapters:
    - instance: test # canal instance Name or mq topic name
      groups:
        - groupId: test
          outerAdapters:
            - name: logger
            - name: rdb
              key: demoDes
              properties:
                jdbc.driverClassName: com.mysql.jdbc.Driver
                jdbc.url: jdbc:mysql://{IP}:3306/test?useUnicode=true
                jdbc.username: root
                jdbc.password: 1234qwer

*配置demo.yml文件

dataSourceKey: demoSrc
destination: test
outerAdapterKey: demoDes
concurrent: true
groupId: test
dbMapping:
    database: test
    table: order
    targetTable: test.order
    targetPk:
        id: id
    mapAll: true
  • 启动com.alibaba.otter.canal.adapter.launcher.CanalAdapterApplication,观察目的数据库。
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现MySQL实时同步MySQL可以借助canal工具来完成。 canal是阿里巴巴开源的一款基于MySQL增量日志解析,仅支持MySQL数据库的日志增量订阅和消费工具。通过订阅MySQLbinlog日志,canal可以获取到数据库增量更新信息,并将这些信息解析后发送给其他应用进行消费。 为了实现MySQL实时同步MySQL,可以按照以下步骤进行操作: 1. 下载并安装canal工具。可以从canal的官方GitHub仓库下载最新版本的canal压缩包,并解压到指定目录。 2. 配置canal。在canal的配置文件中,需要设置MySQL的连接信息、要订阅的数据库和表信息等。 3. 启动canal。在命令行中切换到canal所在的目录,执行启动命令,让canal开始监听MySQLbinlog日志。 4. 消费binlog信息。通过编写Java等编程语言的消费端程序,连接到canal并接收解析后的binlog信息。在消费端程序中,可以根据业务需求将解析后的增量更新信息同步到另一个MySQL数据库中。 需要注意的是,由于canal只是将MySQL增量日志解析成了结构化的数据,并没有提供具体同步MySQL的功能。因此,在步骤4中编写的消费端程序需要自行实现将解析后的binlog信息同步到另一个MySQL数据库的逻辑。 值得一提的是,canal还支持其他类型的消息队列,如Kafka等,通过消息队列可以实现更多应用场景下的实时数据同步。 总结而言,利用canal工具可以实现MySQL实时同步MySQL,通过订阅MySQLbinlog日志并解析后发送给消费端程序,再进行相应的同步操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值