canal 作为数据平台的一个重要环节, 若存在单点故障, 对整体后端的影响是非常大的. 实践和经验告诉我们, 关键重要的服务都要进行failover, 以保证系统的可用性. 下面就来介绍一下 canal 搭配 zookeeper 的 HA 方案.
环境搭建
下载并解压canal.deployer-1.0.22.tar.gz
改名为canal.deployer-1.0.22-master
, 作为第一个提供服务的 canal server
再复制一份为canal.deployer-1.0.22-standby
, 作为 canal master failover
的备援机.
canal master 设置
vim canal.deployer-1.0.22_master/conf/canal.properties
canal.zkServers=127.0.0.1:2181 |
vim canal.deployer-1.0.22_master/conf/example/instance.properties
canal.instance.mysql.slaveId = 1234 |
canal standby 配置
vim canal.deployer-1.0.22_standby/conf/canal.properties
canal.id=2 |
vim canal.deployer-1.0.22_standby/conf/example/instance.properties
canal.instance.mysql.slaveId = 1235 |
启动 zookeeper
bin/zkServer.sh start
, 具体配置略过.
启动 canal
启动 canal master
$ bin/startup.sh |
查看example下的日志, 可知canal正在提供服务.
启动 canal standby
$ bin/startup.sh |
启动后, 发现并没有example的log, 因为当前只有 canal master 在提供服务:
$ ll logs/ |
查看zookeeper中的running节点
|
此时cid
为1, master canal 正在 serving.
client 消费数据
canal client 代码:
CanalConnector connector = CanalConnectors.newClusterConnector("127.0.0.1:2181", destination, "", ""); |
连接 canal server 后, 从日志可以看到更改的数据 :
2016-11-07 09:02:12.527 [main] INFO org.apache.zookeeper.ZooKeeper - Client environment:java.library.path=.::/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib |
连接后, 在zookeeper可以看到 client 的信息:
[zk: localhost:2181(CONNECTED) 0] get /otter/canal/destinations/example/1001/running |
数据消费成功后,canal server 会在zookeeper中记录下当前最后一次消费成功的 binlog 位置, 以便下次重启client时,可从这个位点继续进行消费.
[zk: localhost:2181(CONNECTED) 1] get /otter/canal/destinations/example/1001/cursor |
master canal 宕机测试
停掉 canal master :
$ bin/stop.sh |
停掉canal server后, 可以看到 client的log发生变化 :
|
随着 canal server 的切换, client 会从zookeeper获取最新的 canal server 地址, 并与之建立连接, 继续消费数据.
接下来再查看当前running节点 :
[zk: localhost:2181(CONNECTED) 3] get /otter/canal/destinations/example/running |
可以看到cid
是2
, canal standby 正在提供服务, zookeeper 这里切换完成.
这时候再修改数据库数据, 测试验证 canal standby 是否能够正常工作:
================> binlog[mysql-bin.000117:473] , executeTime : 1478480560000 , delay : 640062ms |
可以看到, canal standby 推送了数据变更给 client, 此时再查看logs/example也会发现有日志出来了:
canal.deployer-1.0.22-SNAPSHOT_standby$ cat logs/example/example.log |
可知新的canal实例已经被启动并接管服务了.
异常场景
当然, 有一些异常场景我们要注意一下:
释放时间
如果canal server的jvm异常crash,running节点(EPHEMERAL type) 的释放是在对应的zookeeper session失效后,
canal server 网络中断
如果 canal server 所在的网络断了, zookeeper将会认为session失效, 进而释放running节点, 而canal server的jvm其实并没有退出.
为了避免瞬间runing失效导致的instance重新分布,canal 有一个策略:
canal server在收到running节点释放后,延迟一段时间抢占running,原本running节点的拥有者可以不需要等待延迟,优先取得running节点,可以保证假死状态下尽可能不无谓的释放资源。 目前延迟时间的默认值为5秒,即running节点针对假死状态的保护期为5秒.