概述
这篇文章的目的是为了讲清楚canal的HA机制,至于什么是HA机制直接套用canal官网原话,因为我自认为没法描述的更好。而我直接从代码的角度去分析如何实现HA的,其实也就是zookeeper的分布式锁的使用方法。
摘录自官网的一段原话:
canal的HA分为两部分,canal server和canal client分别有对应的ha实现:
canal server: 为了减少对mysql dump的请求,不同server上的instance要求同一时间只能有一个处于running,其他的处于standby状态。
canal client: 为了保证有序性,一份instance同一时间只能由一个canal client进行get/ack/rollback操作,否则客户端接收无法保证有序。
canal HA 架构图
说明
图片来自官网的剪切,讲述的很清楚,就不再多说什么了,后面会基于这个图从代码角度展开讲解。
canal server HA
canal server的HA是其实我觉得从我自己的理解应该分为两个角度去讲解,一个是在启动的时候抢占并负责启动提供服务,另外一个是在发生fail-over后抢占并负责启动提供服务。
能把这两个过程讲解清楚我觉得就够了,就能理解server的HA机制了,也基本了解了如何通过zookeeper去实现互斥锁。
最后我们需要问自己的一个问题,就是发生HA切换的时候状态数据同步在两个切换的server之间进行同步呢,很简单,因为我们的数据都是记录在zookeeper上的。
server 启动HA
server在启动过程中,通过以下几步来实现抢占服务启动,入口类在CanalController。
1、对临时节点(/otter/canal/destinations/xxxx/running)进行监听。
2、通过创建临时节点来抢占锁,成功就提供服务。
3、抢占锁成功后启动embededCanalServer开始提供服务。
4、创建的临时节点内部将自己的ip+port暴露出去给client使用。
说明
启动服务的入口函数,别看是runningMonitor,其实是内部负责启动canal instance实例的。
说明
这里最重要的一个点就是对canal的临时节点监控用于在fail-over的时候能够感知到并及时启动stand-by的canal server提供服务。
说明
负责创建临时节点来确认自己是否能够提供服务,这其实通过zookeeper的特性来实现的。
说明
真正启动canal instance的过程,负责同步mysql的数据到canal instance。
server fail-over ha
server 在fail-over过程能够及时发现并完成切换的原因是通过zookeeper的watch机制来实现,如果watch的节点消失了那么其他监听的canal server都能感知到并发起新一轮的抢占并提供服务。
需要区分两个zookeeper事件,分别是节点内容变更事件、节点删除事件,下面有具体说明。
关键字:zookeeper的watch机制,通知,重新抢占。
说明
这里区分了两种情况,节点内容变更事件、节点本身消失事件。对于这两种情况区分简单区分一下进行说明。我估计很多人跟我的疑惑一样,为啥要区分这两个事件呢,其实我的猜测是如果节点删除了说明这个服务停止了跟mysql的同步也就结束了,但是如果节点内容变更了,可能因为其他一些原因,譬如我们手动修改zk节点内容之类的,这个时候我们需要处理连接释放的过程。
节点本身消失处理是handleDataDeleted函数内部的操作,可以看出来其实就做一件事情,重新开始新一轮的抢占,initRunning就是我们刚刚讲的抢占逻辑,可以翻看start-ha-3这个图片。唯一的区别是节点消失事件前提供服务的如果是自身就具有优先抢占的权利,否则就随机进行个delay操作避免同时大面积并发抢占。
我们重点关注下节点内容变更的事件吧,之所以需要额外关注这个事件是因为中间涉及到如果是如果变更前是自身就需要释放连接资源。
资源释放过程
说明
在收到节点内容变更事件后就开始进入资源释放过程
说明
停止canal的embededCanalserver的服务,结束从mysql的数据同步。
canal client HA
整体来说,canal client的HA和canal server的HA机制是一模一样的,它的实现逻辑其实在创建cluster client的时候用的封装zookeeper的客户端,然后zookeeper的客户端去检测canal server节点内容的变化并重新初始化连接而已。
说明
这个地方很明显看出来,我们首先连接的zookeeper,原因应该很清楚,因为我们需要从zookeeper获取提供服务的canal server的地址,在/otter/canal/destinations/destination/running节点去获取。
说明
这部分其实就是client和zookeeper交互的部分,负责实时感知节点变化并重新初始化连接,保证client端的HA。