前几天在网上冲浪的时候发现了一个比较成熟的开源中间件——Canal。在了解了它的工作原理和使用场景后,顿时产生了浓厚的兴趣。今天,就让我们跟随我的脚步,一起来揭开它神秘的面纱吧。
简介
canal 翻译为管道,主要用途是基于 MySQL 数据库的增量日志 Binlog 解析,提供增量数据订阅和消费。
早期阿里巴巴因为杭州和美国双机房部署,存在跨机房同步的业务需求,实现方式主要是基于业务 trigger 获取增量变更。从 2010 年开始,业务逐步尝试数据库日志解析获取增量变更进行同步,由此衍生出了大量的数据库增量订阅和消费业务。
基于日志增量订阅和消费的业务包括
-
数据库镜像;
-
数据库实时备份;
-
索引构建和实时维护(拆分异构索引、倒排索引等);
-
业务 cache 刷新;
-
带业务逻辑的增量数据处理;
当前的 canal 支持源端 MySQL 的版本包括 5.1.x,5.5.x,5.6.x,5.7.x,8.0.x。
工作原理
MySQL主备复制原理
-
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 流);
github地址:https://github.com/alibaba/canal
完整wiki地址:https://github.com/alibaba/canal/wiki
Canal架构
一个 server 代表一个 canal 运行实例,对应于一个 jvm,一个 instance 对应一个数据队列。
instance模块:
-
eventParser :数据源接入,模拟 slave 协议和 master 进行交互,协议解析;
-
eventSink :Parser 和 Store 链接器,进行数据过滤、加工、分发的工作;
-
eventStore :数据存储;
-
metaManager :增量订阅&消费信息管理器;
instance 是 canal 数据同步的核心,在一个 canal 实例中只有启动 instace 才能进行数据的同步任务。一个 canal server 实例中可以创建多个 Canal Instance 实例。每一个 Canal Instance 可以看成是对应一个 MySQL 实例。
Canal-HA机制
所谓 HA 即高可用,是 High Available 的简称。通常我们一个服务要支持高可用都需要借助于第三方的分布式同步协调服务,最常用的是zookeeper 。canal 实现高可用,也是依赖了zookeeper 的几个特性:watcher 和 EPHEMERAL 节点。
canal 的高可用分为两部分:canal server 和 canal client
-
canal server: 为了减少对 mysql dump 的请求,不同 server 上的 instance(不同 server 上的相同 instance)要求同一时间只能有一个处于 running,其他的处于 standby 状态,也就是说,只会有一个 canal server 的 instance 处于 active 状态,但是当这个 instance down 掉后会重新选出一个 canal server。
-
canal client: 为了保证有序性,一份 instance 同一时间只能由一个 canal client 进行 get/ack/rollback 操作,否则客户端接收无法保证有序。
server ha 的架构图如下:
大致步骤:
-
canal server 要启动某个 canal instance 时都先向 zookeeper 进行一次尝试启动判断(实现:创建 EPHEMERAL 节点,谁创建成功就允许谁启动);
-
创建 zookeeper 节点成功后,对应的 canal server 就启动对应的 canal instance,没有创建成功的 canal instance 就会处于 standby 状态。
-
一旦 zookeeper 发现 canal server A 创建的 instance 节点消失后,立即通知其他的 canal server 再次进行步骤1的操作,重新选出一个 canal server 启动 instance。
-
canal client 每次进行 connect 时,会首先向 zookeeper 询问当前是谁启动了canal instance,然后和其建立链接,一旦链接不可用,会重新尝试 connect。
Canal Client 的方式和 canal server 方式类似,也是利用 zookeeper 的抢占 EPHEMERAL 节点的方式进行控制。
应用场景
同步缓存 Redis /全文搜索 ES
当数据库变更后通过 binlog 进行缓存/ES的增量更新。当缓存/ES更新出现问题时,应该回退 binlog 到过去某个位置进行重新同步,并提供全量刷新缓存/ES的方法。
下发任务
当数据变更时需要通知其他依赖系统。其原理是任务系统监听数据库变更,然后将变更的数据写入 MQ/kafka 进行任务下发,比如商品数据变更后需要通知商品详情页、列表页、搜索页等相关系统。