一般来说,我们对于数据库最主要的要求就是:数据不丢。不管是主从复制,还是使用类似otter+canal这样的数据库同步方案,我们最基本的需求是,在数据不丢失的前提下,尽可能的保证系统的高可用,也就是在某个节点挂掉,或者数据库发生主从切换等情况下,我们的数据同步系统依然能够发挥它的作用–数据同步。本文讨论的场景是数据库发生主从切换,本文将从源码的角度,来看看otter和canal是如何保证高可用和高可靠的。
一、EventParser
通过阅读文档和源码,我们可以知道,对于一个canal server,基础的框架包括以下几个部分:MetaManager、EventParser、EventSink和EventStore。其中EventParser的作用就是发送dump命令,从mysql数据库获取binlog文件。发送dump命令,可以指定时间戳或者position,从指定的时间或者位置开始dump。我们来看看过程:
首先是CanalServer启动。otter默认使用的是内置版的canal server,所以我们主要看CanalServerWithEmbedded这个类。来看下他的启动过程:
public void start(final String destination) {
final CanalInstance canalInstance = canalInstances.get(destination);
if (!canalInstance.isStart()) {
try {
MDC.put("destination", destination);
canalInstance.start();//启动实例
logger.info("start CanalInstances[{}] successfully", destination);
} finally {
MDC.remove("destination");
}
}
}
我们看下实例启动那一行,跟到AbstractCanalInstance类中
public void start() {
super.start();
if (!metaManager.isStart()) {
metaManager.start();//源数据管理启动
}
if (!alarmHandler.isStart()) {
alarmHandler.start();//报警处理器启动
}
if (!eventStore.isStart()) {
eventStore.start();//数据存储器启动
}
if (!eventSink.isStart()) {
eventSink.start();//数据过滤器启动
}
if (!eventParser.isStart()) {
//数据解析器启动
beforeStartEventParser(eventParser);
eventParser.start();
afterStartEventParser(eventParser);