基本需求
- 网络不可靠,异地机房尤为明显.
- manager/node的jvm不可靠,需要考虑异常crash情况
- node的jvm不可靠,需要考虑异常crash的情况
- 数据库不可靠,需要考虑数据库切换,比如binlog获取和数据载入时,都需要考虑数据库HA机制
- 系统发布时,排除正常的jvm关闭和启动
实现思路
1. 考虑node和manager独立部署
manager对于node来说可以是一个optional的环境,只有在第一次启动任务时需要,node一旦启动了同步任务后,无论manager是否可用,不能影响正常同步。
需要考虑的点:
- node对于配置需要有本地cache
- node推送统计信息到manager需要有容错处理,需要考虑manager failover(一台manager挂了,需要链接到另一台).
目前otter内部,manager部署2台,manager主要集中在杭州机房,node部署70+,node分布在各个机房。
2. 建议异常流程处理机制
otter调度系统在设计的时候,会有个假定,认为90%的情况都是正常工作的,所以一旦出现异常,处理的代价相对比较高,会使用分布式锁机制。
仲裁器设计了三种异常机制指令:
- WARNING : 只发送报警信息,不做任何S/E/T/L调度干预
- ROLLBACK : 尝试获取分布式锁,避免并发修改,其次修改分布式Permit为false,停止后续的所有S/E/T/L调度,然后删除所有当前process调度信息,通过zookeeper watcher通知所有相关node,清理对应process的上下文,pipe的数据存储会通过TTL来进行清理,不需要ROLLBACK干预。完成后,释放锁操作
- RESTART : 前面几个步骤和ROLLBACK基本类似,唯一不同点在于,在释放锁之前会尝试修改分布式Permit为true,重新开启同步,然后释放锁.
罗列了一下不同异常对应的处理机制:
- 两个节点通讯时网络异常,节点发起ROLLBACK
- 节点执行S/E/T/L模块,比如写数据库出现网络异常,节点发起ROLLBACK
- 节点发生了CRASH,由manager进行监听,manager发现后发起RESTART
3. node节点监控原理:(和hadoop/hbase原理基本一致,利用zookeeper)
- 每个node在启动完成后,都会在zookeeper中创建一个Ephemerals节点(此节点特点,当node节点发生crash之后,与zookeeper建立的sesstion因为没有心跳,超过一定时间后就会出现SesstionExpired,然后zookeeper会删除该节点)
- manager监听整个node节点列表的变化,任何一个node节点的消失,都会收到zookeeper watcher通知,与内存中上一个版本进行比较,判断出当前消失的node节点
- 针对该消失的node节点,会有一段保护期(因为可能正常的发布,会关闭node,同样会触发该watcher),如果该node在保护期内重新启动了,则不做任何处理。默认保护期为90秒
- 如果保护期内node节点未正常启动,说明node是异常crash,通过查询配置,找到使用了该node的所有同步任务,对每个同步任务发起一个RESTART指令,让所有同步任务重新做一次负载均衡选择,避免挂死在老的node上,一直死等其结果返回。
4. 数据库切换
数据库异常问题多种多样,比如数据库hang住,数据库不可用,数据库不可写等等。 在阿里巴巴内部一般会有DBA控制数据库的切换问题。
比如会有一套管理系统,配置当前mysql主备的关系,发现主机不可用时,他们会通过该系统切备机变为主机,然后推送该配置到所有节点,然后各个客户端收到主备切换消息,更改自己的数据库链接,完成数据库切换。
因为内部系统无法直接开源,在otter开源版本中,也自带了一个简单版的数据库主备推送的机制,通过页面上的切换按钮,就可以通知到所有的otter节点,切换数据库链接,包括canal的binlog解析和otter数据库loader等。
otter内部配置中称之为主备配置(media配置),为一对主备IP,定义一个groupKey。然后在各个地方使用该groupKey。
- 比如jdbc url使用group后为:jdbc:mysql://groupKey=xxxx
- canal中可以选择HA机制为media,然后填入对应的groupKey即可
发现需要做数据库切换了,可以直接点击切换按钮,目前otter的实现为定时轮询非推送,一般需要1分钟左右才会正式生效,或者发生一次RESTART指令。同样,主备切换可以暴露为服务,方便大家接入各自的数据库管理平台,这也是otter抽象这么一层主备切换配置的原因