一、canal模擬mysql slave的交互協議,假裝本身爲mysql slave,向mysql master發送dump協議mysql
二、mysql master收到dump請求,開始推送(slave拉取,不是master主動push給slaves)binary log給slave(也就是canal)sql
三、canal解析binary log對象(原始爲byte流) api
組件說明:session
server表明一個canal運行實例,對應於一個jvm架構
instance對應於一個數據隊列(1個server對應1..n個instance)異步
而instance模塊又由eventParser(數據源接入,模擬slave協議和master進行交互,協議解析)、eventSink(Parser和Store鏈接器,進行數據過濾,加工,分發的工做)、eventStore(數據存儲)和metaManager(增量訂閱&消費信息管理器)組成。jvm
EventParser在向mysql發送dump命令以前會先從Log Position中獲取上次解析成功的位置(若是是第一次啓動,則獲取初始指定位置或者當前數據段binlog位點)。mysql接受到dump命令後,由EventParser從mysql上pull binlog數據進行解析並傳遞給EventSink(傳遞給EventSink模塊進行數據存儲,是一個阻塞操做,直到存儲成功),傳送成功以後更新Log Position。流程圖以下: 指針
EventSink起到一個相似channel的功能,能夠對數據進行過濾、分發/路由(1:n)、歸併(n:1)和加工。日誌
EventSink是鏈接EventParser和EventStore的橋樑。code
EventStore實現模式是內存模式,內存結構爲環形隊列,由三個指針(Put、Get和Ack)標識數據存儲和讀取的位置。
MetaManager是增量訂閱&消費信息管理器,增量訂閱和消費之間的協議包括get/ack/rollback,分別爲: Message getWithoutAck(int batchSize),容許指定batchSize,一次能夠獲取多條,每次返回的對象爲Message,包含的內容爲:batch id[惟一標識]和entries[具體的數據對象]
void rollback(long batchId),顧命思議,回滾上次的get請求,從新獲取數據。基於get獲取的batchId進行提交,避免誤操做
void ack(long batchId),顧命思議,確認已經消費成功,通知server刪除數據。基於get獲取的batchId進行提交,避免誤操做
canal的get/ack/rollback協議和常規的jms協議有所不一樣,容許get/ack異步處理,好比能夠連續調用get屢次,後續異步按順序提交ack/rollback,項目中稱之爲流式api.
canal是支持HA的,其實現機制也是依賴zookeeper來實現的,用到的特性有watcher和EPHEMERAL節點(和session生命週期綁定),與HDFS的HA相似
canal的ha分爲兩部分,canal server和canal client分別有對應的ha實現
canal server: 爲了減小對mysql dump的請求,不一樣server上的instance(不一樣server上的相同instance)要求同一時間只能有一個處於running,其餘的處於standby狀態(standby是instance的狀態)。
canal client: 爲了保證有序性,一份instance同一時間只能由一個canal client進行get/ack/rollback操做,不然客戶端接收沒法保證有序。
server ha的架構圖以下:
canal server要啓動某個canal instance時都先向zookeeper進行一次嘗試啓動判斷(實現:建立EPHEMERAL節點,誰建立成功就容許誰啓動)
建立zookeeper節點成功後,對應的canal server就啓動對應的canal instance,沒有建立成功的canal instance就會處於standby狀態。
一旦zookeeper發現canal server A建立的instance節點消失後,當即通知其餘的canal server再次進行步驟1的操做,從新選出一個canal server啓動instance。
canal client每次進行connect時,會首先向zookeeper詢問當前是誰啓動了canal instance,而後和其創建連接,一旦連接不可用,會從新嘗試connect。
Canal部署及使用
MySQL配置
canal同步數據須要掃描MySQL的binlog日誌,而binlog默認是關閉的,須要開啓,而且爲了保證同步數據的一致性,使用的日誌格式爲row-based replication(RBR),在my.conf中開啓binlog,
[mysqld] log-bin=mysql-bin #添加這一行就ok binlog-format=ROW #選擇row模式 server_id=1 #配置mysql replaction須要定義,不能和canal的slaveId重複
更改my.conf以後,須要重啓MySQL,重啓的方式有不少找到合適本身的就行。