记Canal 数据备份的使用和总结

26 阅读4分钟

数据备份的原理

在小的公司如果有自己的服务器,有自己的业务数据,都应该做数据备份处理。要么做定时备份要么做实时备份。

其实 Mysql 本身提供了主从分布等几个备份方案,但是健壮程度一言难尽。所以在做数据备份的时候,我选择了 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 是阿里巴巴的一款开源的 MySQL binlog 增量订阅&消费组件。它的原理是:

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

图片

搭建同步系统前的准备

同步需要的工具主要是主要是Adapter(适配器-消费者)和Deployer(生产者)。

Deployer主要是用于接收,MYSQL主服数据库传过来的 binary log 数据。

Adapter 主要是用于接收Deployer产生的数据,同步到数据库中。

Mysql 主数据库的 my.cnf 需要有以下配置:

log-bin=mysql-bin # 开启 binlog
binlog-format=ROW # 选择 ROW 模式
server_id=1 # 配置 MySQL replaction 需要定义,不要和 canal 的 slaveId 重复

配置完 my.cnf,需要创建一个用户,用于 Canal 的授权访问,执行以下语句:

#授权 canal 链接 MySQL 账号具有作为 MySQL slave 的权限, 如果已有账户可直接 
grantCREATE USER canal IDENTIFIED BY 'canal';
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'IP';
-- GRANT ALL PRIVILEGES ON *.* TO 'canal'@'%' ;
FLUSH PRIVILEGES;
SET PASSWORD FOR 'canal'@'IP' = PASSWORD('123456');
FLUSH PRIVILEGES;
#IP位置自行更换主数据库的IP地址。

在另外一个服务器搭建一个 Mysql 数据库,配置可以和上面的 my.cnf 一样。

show variables like 'log_bin';
show variables like "%binlog_format%";
show variables like "%server_id%";

查看配置是否正确,然后执行下面语句得到结果:

show master status;
#mysql-bin.000276   120	data	mysql	

停止能对数据库产生影响的服务,开始对数据库备份。

Canal的同步机制可以为整库备份,也可以选择备份几张重要的表。备份结束后,再次执行上面语句,查看结果看看是否一致,如果不一致重复这两步,直至结果一致。

将备份的数据文件传送到备份数据库服务器,恢复数据。

搭建同步系统

配置 Deployer。配置文件为

deployer\conf\example\instance. properties

# position info
#填写备份服务器IP和数据库端口
canal.instance.master.address=192.168.0.2:3306
#配置上面语句得到的结果
canal.instance.master.journal.name=mysql-bin.000276
canal.instance.master.position=120
canal.instance.master.timestamp=canal.instance.master.gtid=
#这里填写的是在主数据库配置的用户
canalcanal.instance.dbUsername=canal
canal.instance.dbPassword=123456
canal.instance.connectionCharset = UTF-8
#如果配置这个参数,说明在主数据库选择了部分表的备份。
#备份什么表这里就填写什么表,data为数据库名canal.instance.filter.regex=data.test_user
#这个参数是要过滤字段的黑名单,配置什么参数将不同步该表的该字段。
#其他字段正常同步
canal.instance.filter.black.field=data.test_home:address

配置 Deployer的系统参数,配置为

deployer\conf\canal.properties

#这里配置上面相同的用户名和密码
canal.instance.tsdb.dbUsername = canal
canal.instance.tsdb.dbPassword = 123456

Deployer的配置完成。在bin下startup启动
配置Adapter。配置文件application.yml

 server:
  port: 8081
spring:
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
    default-property-inclusion: non_null

canal.conf:
  mode: tcp #tcp kafka rocketMQ rabbitMQ #用tcp的方式进行数据同步
  flatMessage: true
  zookeeperHosts:
  syncBatchSize: 1000
  retries: -1
  timeout:
  accessKey:
  secretKey:
  consumerProperties:
    # canal tcp consumer
    canal.tcp.server.host: 127.0.0.1:11111
    canal.tcp.zookeeper.hosts:
    canal.tcp.batch.size: 500
    canal.tcp.username:
    canal.tcp.password:
  srcDataSources:#主数据的配置
    defaultDS:
      url: jdbc:mysql://192.168.1.1:3306/data?characterEncoding=utf8&serverTimezone=Asia/Shanghai
      username: canal
      password: 123456
  canalAdapters:
  - instance: example # canal instance Name or mq topic name
    groups:
    - groupId: g1
      outerAdapters:#从数据库的配置
      - name: logger
      - name: rdb
        key: mysql1
        properties:
          jdbc.driverClassName: com.mysql.jdbc.Driver
          jdbc.url: jdbc:mysql://127.0.0.1:3306/data?characterEncoding=utf8&serverTimezone=Asia/Shanghai
          jdbc.username: root
          jdbc.password:
          druid.stat.enable: false
          druid.stat.slowSqlMillis: 1000


在 rdb下,需要配置对应表的操作文件,这样才能将接收到的信息流同步到对应的表中。配置一个 test_user.yml

dataSourceKey: defaultDS
destination: example
groupId: g1
outerAdapterKey: mysql1
concurrent: true
dbMapping:
  database: data
  table: test_user
  targetTable: test_user
  targetPk:#主键,如果是联合主键,可以在下面继续写字段
    uid: uid
  mapAll: true#所有字段一一对应。Deployer中可以过滤字段,所以这里这样配置也不会出错

所有表都配置完毕就可以启动 Adapter了,在 bin下startup启动。如果启动报数据库错误,可以尝试更换mysql-connector-java-5.1.48.jar到最新版本。
以上就是不写代码的情况下,搭建了一个 tcp 模式下的 Mysql 主从同步机制。