Canal是阿里巴巴開源的一款數(shù)據(jù)庫同步組件,它通過分析MySQL數(shù)據(jù)庫的更新日志Binlog將更新的數(shù)據(jù)推送到不同的消費(fèi)方來達(dá)到數(shù)據(jù)同步的目的;
首先要了解,MySQL數(shù)據(jù)庫是一種日志優(yōu)先的數(shù)據(jù)庫,日志優(yōu)先意思是每次在更新數(shù)據(jù)時(shí)先將修改的數(shù)據(jù)信息寫入日志,然后才會(huì)進(jìn)行數(shù)據(jù)更新,這樣做的目的是保證高可用性,如果數(shù)據(jù)更新異常,可以通過日志來操作回滾或重試;MySQL日志以二進(jìn)制的方式存儲(chǔ),因此簡稱為BinLog(BinaryLog);
當(dāng)MySQL數(shù)據(jù)庫存在主從庫時(shí),主庫會(huì)將BinLog發(fā)送到從庫稱為RelayLog,從庫會(huì)根據(jù)RelayLog對(duì)從庫數(shù)據(jù)進(jìn)行同樣的修改,從而達(dá)到主從數(shù)據(jù)一致的目的;
MySQL的日志格式有三種:行模式、命令模式、混合模式;
行模式:日志中會(huì)記錄每一行數(shù)據(jù)被修改的形式,然后在slave端再對(duì)相同的數(shù)據(jù)進(jìn)行修改
優(yōu)點(diǎn):在行模式下,binlog可以不記錄執(zhí)行的sql語句信息,僅僅記錄每一行數(shù)據(jù)修改之前的值和修改之后的值,binlog會(huì)非常清楚的記錄下每一行數(shù)據(jù)修改的細(xì)節(jié)。不會(huì)出現(xiàn)語句模式中主從不一致的問題
缺點(diǎn):所有的執(zhí)行的語句當(dāng)記錄到日志中的時(shí)候,都將以每行記錄的修改來記錄,會(huì)產(chǎn)生大量的日志內(nèi)容
Statement Level 語句模式(默認(rèn)):每一條會(huì)修改數(shù)據(jù)的sql都會(huì)記錄到master的bin-log中。slave在復(fù)制的時(shí)候sql進(jìn)程會(huì)解析成和原來master端執(zhí)行過的相同的sql來再次執(zhí)行
優(yōu)點(diǎn):首先就是解決了行模式的下的缺點(diǎn),不需要記錄每一行數(shù)據(jù)的變化,減少binlog日志量,節(jié)約IO,提高性能
缺點(diǎn):由于只記錄語句,所以在語句模式下,已經(jīng)發(fā)現(xiàn)了有不少情況下會(huì)造成主從不一致的問題,例如使用系統(tǒng)函數(shù)UUID(),用戶自定義方法,存儲(chǔ)過程,觸發(fā)器等
Mixed 混合模式:MySQL會(huì)根據(jù)執(zhí)行的每一條具體的sql語句來區(qū)分對(duì)待記錄的日志格式,也就是在Statement和Row之間選擇一種
Canal的實(shí)現(xiàn)原理很簡單,CanalServer通過模擬slave從庫向主庫發(fā)送dump請(qǐng)求,主庫接收到dump請(qǐng)求后會(huì)向其發(fā)送BinLog,Canal對(duì)接收到的字節(jié)流形式的binlog進(jìn)行解析;

Canal的架構(gòu):

server代表一個(gè)canal運(yùn)行實(shí)例,對(duì)應(yīng)于一個(gè)jvm
instance對(duì)應(yīng)于一個(gè)數(shù)據(jù)隊(duì)列 (1個(gè)server對(duì)應(yīng)1..n個(gè)instance),負(fù)責(zé)模擬不同的DB-Slave,一個(gè)instance對(duì)應(yīng)一個(gè)DB,因此server與instance為一對(duì)多的關(guān)系,當(dāng)監(jiān)聽多個(gè)DB的數(shù)據(jù)變化就會(huì)有多個(gè)instance;
eventParser 數(shù)據(jù)源接入,模擬slave協(xié)議和master進(jìn)行交互,協(xié)議解析
eventSink Parser和Store鏈接器,進(jìn)行數(shù)據(jù)過濾,加工,分發(fā)的工作
eventStore 數(shù)據(jù)存儲(chǔ)
metaManager 增量訂閱&消費(fèi)信息管理器
在Canal架構(gòu)中要重點(diǎn)介紹一下Event的存儲(chǔ),目前只實(shí)現(xiàn)了內(nèi)存模式,即Event存放在內(nèi)存中;
其存儲(chǔ)結(jié)構(gòu)為RingBuffer:


Put: Sink模塊進(jìn)行數(shù)據(jù)存儲(chǔ)的最后一次寫入位置
Get: 數(shù)據(jù)訂閱獲取的最后一次提取位置
Ack: 數(shù)據(jù)消費(fèi)成功的最后一次消費(fèi)位置
Event的存儲(chǔ)數(shù)量是有限制的,當(dāng)RingBuffer存放不下新的Event時(shí)會(huì)通知Master延遲發(fā)送binlog;
Canal的高可用性時(shí)通過Zookeeper來保證的:
為了減少對(duì)mysql dump的請(qǐng)求,不同server上的instance要求同一時(shí)間只能有一個(gè)處于running,其他的處于standby狀態(tài);
Canal原生支持HA機(jī)制下啟動(dòng),只需配置相關(guān)的配置,無需額外的工作量;
Canal Server HA機(jī)制啟動(dòng)流程(如圖所示)

第一步當(dāng)不同sever上的監(jiān)聽相同DB的instance嘗試啟動(dòng)時(shí),需要去Zookeeper上注冊(cè)節(jié)點(diǎn),如果發(fā)現(xiàn)沒有活躍節(jié)點(diǎn),則進(jìn)行啟動(dòng),否則進(jìn)入StandBy狀態(tài),當(dāng)正在運(yùn)行的instance出現(xiàn)故障時(shí),比如ServerA 掛掉了,這時(shí)Zookeeper檢測到ServerA上的instance已經(jīng)不可用,通知ServerB上相應(yīng)的instance進(jìn)行啟動(dòng);
通過上面我們已經(jīng)了解了CanalServer的具體實(shí)現(xiàn)原理,CanalSever只是實(shí)現(xiàn)了對(duì)數(shù)據(jù)庫信息更新的感知,需要有相應(yīng)的消費(fèi)者來消費(fèi)這些消息來達(dá)到各自的業(yè)務(wù)目標(biāo),Otter同樣是阿里巴巴開源的一款工具,它可以對(duì)數(shù)據(jù)庫變更的信息進(jìn)行統(tǒng)一消費(fèi)并按照不同的方式推送到各個(gè)消費(fèi)方,而使用者只需在Otter平臺(tái)上配置相應(yīng)的規(guī)則即可實(shí)現(xiàn);
