*备注地址~https://github.com/alibaba/canal、https://github.com/alibaba/canal/wiki/AdminGuide
一、简介
1、源起
canal [kə’næl],译意为水道/管道/沟渠,纯Java开发,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费,
早期阿里巴巴因为杭州和美国双机房部署,存在跨机房同步的业务需求,实现方式主要是基于业务 trigger 获取增量变更。从 2010 年开始,业务逐步尝试数据库日志解析获取增量变更进行同步,由此衍生出了大量的数据库增量订阅和消费业务。
基于日志增量订阅和消费的业务包括
- 数据库镜像
- 数据库实时备份
- 索引构建和实时维护(拆分异构索引、倒排索引等)
- 业务 cache 刷新(缓存一致性)
- 带业务逻辑的增量数据处理
当前的 canal 支持源端 MySQL 版本包括 5.1.x , 5.5.x , 5.6.x , 5.7.x , 8.0.x
2、结构
- canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送 dump 协议
- MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal )
- canal 解析 binary log 对象(原始为 byte 流)
通过以上原理,很容易理解canal的数据同步逻辑:就是把canal实例伪装为mysql的一个从库实例,通过mysql自有的数据同步机制来达到数据同步的目的。
上图可知canal内部设计为server-client的结构。
可把同步数据直接透传到kafka和rocket mq队列。
可通过client端api定制消费mysql同步数据。可也通过adapter api扩展实现HBASE、Rdb、ES的数据同步。
二、工作原理
1、MySQL主备复制原理
- MySQL master 将数据变更写入二进制日志( binary log, 其中记录叫做二进制日志事件binary log events,可以通过 show binlog events 进行查看)
- MySQL slave(I/O thread) 将 master 的 binary log events 拷贝到它的中继日志(relay log)
MySQL slave(SQL thread) 重放 relay log 中事件,将数据变更反映它自己的数据
启用Binlog注意以下几点:
Master主库一般会有多台Slave订阅,且Master主库要支持业务实时变更操作,服务器资源会有瓶颈
- 需要同步的数据表一定要有主键
2、canal 工作原理
- canal 模拟 MySQL slave 的交互协议,伪装自己为 MySQL slave ,向 MySQL master 发送dump 协议
- MySQL master 收到 dump 请求,开始推送 binary log 给 slave (即 canal )
- canal 解析 binary log 对象(原始为 byte 流)
- 把MySQL的binlog设置为row模式以后,可以获取到执行的每一个Insert/Update/Delete的脚本,以及修改前和修改后的数据,基于这个特性,Canal就能高效的获取到MySQL数据的变更。
- 目前canal只能支持row模式的增量订阅(statement只有sql,没有数据,所以无法获取原始的变更日志)
3、Canal是怎么假装成Mysql Slave的?
- 与Mysql Master服务器建立Socket链接;
- 根据Mysql协议规范发送身份认证数据包进行身份认证;
- 根据Mysql协议规范发送slave注册数据包将自己伪装成Mysql Slave;
- 根据Mysql协议规范发送Dump请求,让Master给自己推送Binlog日志;
4、Canal解析binlog
Mysql Binlog介绍:http://dev.mysql.com/doc/refman/5.5/en/binary-log.html
一个binlog包含一个四字节的模数和一系列描述数据变更的Event,每一个Event又包含header和data两部分,大致结构如下:
基于Row模式的binlog主要包括以下几个Event:
- TABLE_MAP_EVENT:描述变更的数据库表
- WRITE_ROWS_EVENT:描述插入数据变更
- UPDATE_ROWS_EVENT:描述修改数据变更
- DELETE_ROWS_EVENT:描述删除数据变更
根据Event的固定结构就可以解析出来相应的数据变更信息。
演示查看binlog:
mysqlbinlog --no-defaults --base64-output=decode-rows -v ../data/binlog.000034 | more
三、架构演化
从上图可以看到Canal是Server-Client模式。
Server,主要是解析、分发、存储binlog;
Client,通过ClientAPI你可以从Server获取变更数据;
ClientAdapter,扩展Client的功能,包括将数据同步到RDB,ES,HBASE;
但其实这种Client模式并没有达到真正的解耦,更关键的是目前只有Java语言的Client,为了解决这个问题,大家自然而然想到消息中间件。
事实上,Canal 1.1.1版本以后也是支持在Canal Server解析binlog以后直接将数据投递到Kafka/RocketMQ。