系列
canal源碼解析(2)—位點(diǎn)的實(shí)現(xiàn)
概述
????這篇文章的目的是為了講清楚canal的HA機(jī)制轨帜,至于什么是HA機(jī)制直接套用canal官網(wǎng)原話兴泥,因?yàn)槲易哉J(rèn)為沒法描述的更好。而我直接從代碼的角度去分析如何實(shí)現(xiàn)HA的坏瘩,其實(shí)也就是zookeeper的分布式鎖的使用方法磕瓷。
? ? 摘錄自官網(wǎng)的一段原話:
????canal的HA分為兩部分,canal server和canal client分別有對應(yīng)的ha實(shí)現(xiàn):
????canal server: 為了減少對mysql dump的請求编振,不同server上的instance要求同一時間只能有一個處于running棉姐,其他的處于standby狀態(tài)。
????canal client: 為了保證有序性庵楷,一份instance同一時間只能由一個canal client進(jìn)行g(shù)et/ack/rollback操作罢艾,否則客戶端接收無法保證有序。
canal HA 架構(gòu)圖
說明
? ? 圖片來自官網(wǎng)的剪切嫁乘,講述的很清楚昆婿,就不再多說什么了,后面會基于這個圖從代碼角度展開講解蜓斧。
canal server HA
????canal server的HA是其實(shí)我覺得從我自己的理解應(yīng)該分為兩個角度去講解仓蛆,一個是在啟動的時候搶占并負(fù)責(zé)啟動提供服務(wù),另外一個是在發(fā)生fail-over后搶占并負(fù)責(zé)啟動提供服務(wù)挎春。
? ? 能把這兩個過程講解清楚我覺得就夠了看疙,就能理解server的HA機(jī)制了,也基本了解了如何通過zookeeper去實(shí)現(xiàn)互斥鎖直奋。
? ? 最后我們需要問自己的一個問題能庆,就是發(fā)生HA切換的時候狀態(tài)數(shù)據(jù)同步在兩個切換的server之間進(jìn)行同步呢,很簡單脚线,因?yàn)槲覀兊臄?shù)據(jù)都是記錄在zookeeper上的搁胆。
server 啟動HA
? ? server在啟動過程中,通過以下幾步來實(shí)現(xiàn)搶占服務(wù)啟動邮绿,入口類在CanalController渠旁。
????1、對臨時節(jié)點(diǎn)(/otter/canal/destinations/xxxx/running)進(jìn)行監(jiān)聽船逮。
????2顾腊、通過創(chuàng)建臨時節(jié)點(diǎn)來搶占鎖,成功就提供服務(wù)挖胃。
????3杂靶、搶占鎖成功后啟動embededCanalServer開始提供服務(wù)。
????4酱鸭、創(chuàng)建的臨時節(jié)點(diǎn)內(nèi)部將自己的ip+port暴露出去給client使用吗垮。
說明
? ? 啟動服務(wù)的入口函數(shù),別看是runningMonitor凛辣,其實(shí)是內(nèi)部負(fù)責(zé)啟動canal instance實(shí)例的抱既。
說明
? ? 這里最重要的一個點(diǎn)就是對canal的臨時節(jié)點(diǎn)監(jiān)控用于在fail-over的時候能夠感知到并及時啟動stand-by的canal server提供服務(wù)。
說明
? ? 負(fù)責(zé)創(chuàng)建臨時節(jié)點(diǎn)來確認(rèn)自己是否能夠提供服務(wù)扁誓,這其實(shí)通過zookeeper的特性來實(shí)現(xiàn)的防泵。
說明
????真正啟動canal instance的過程蚀之,負(fù)責(zé)同步mysql的數(shù)據(jù)到canal instance。
server fail-over ha
????server 在fail-over過程能夠及時發(fā)現(xiàn)并完成切換的原因是通過zookeeper的watch機(jī)制來實(shí)現(xiàn)捷泞,如果watch的節(jié)點(diǎn)消失了那么其他監(jiān)聽的canal server都能感知到并發(fā)起新一輪的搶占并提供服務(wù)足删。
? ? 需要區(qū)分兩個zookeeper事件,分別是節(jié)點(diǎn)內(nèi)容變更事件锁右、節(jié)點(diǎn)刪除事件失受,下面有具體說明。
? ? 關(guān)鍵字:zookeeper的watch機(jī)制咏瑟,通知拂到,重新?lián)屨肌?/p>
說明
? ? 這里區(qū)分了兩種情況,節(jié)點(diǎn)內(nèi)容變更事件码泞、節(jié)點(diǎn)本身消失事件兄旬。對于這兩種情況區(qū)分簡單區(qū)分一下進(jìn)行說明。我估計(jì)很多人跟我的疑惑一樣余寥,為啥要區(qū)分這兩個事件呢领铐,其實(shí)我的猜測是如果節(jié)點(diǎn)刪除了說明這個服務(wù)停止了跟mysql的同步也就結(jié)束了,但是如果節(jié)點(diǎn)內(nèi)容變更了宋舷,可能因?yàn)槠渌恍┰蛐髂欤┤缥覀兪謩有薷膠k節(jié)點(diǎn)內(nèi)容之類的,這個時候我們需要處理連接釋放的過程祝蝠。
? ? 節(jié)點(diǎn)本身消失處理是handleDataDeleted函數(shù)內(nèi)部的操作音诈,可以看出來其實(shí)就做一件事情,重新開始新一輪的搶占绎狭,initRunning就是我們剛剛講的搶占邏輯改艇,可以翻看start-ha-3這個圖片。唯一的區(qū)別是節(jié)點(diǎn)消失事件前提供服務(wù)的如果是自身就具有優(yōu)先搶占的權(quán)利坟岔,否則就隨機(jī)進(jìn)行個delay操作避免同時大面積并發(fā)搶占。
? ? 我們重點(diǎn)關(guān)注下節(jié)點(diǎn)內(nèi)容變更的事件吧摔桦,之所以需要額外關(guān)注這個事件是因?yàn)橹虚g涉及到如果是如果變更前是自身就需要釋放連接資源社付。
資源釋放過程
說明
? ? 在收到節(jié)點(diǎn)內(nèi)容變更事件后就開始進(jìn)入資源釋放過程
說明
? ? 停止canal的embededCanalserver的服務(wù),結(jié)束從mysql的數(shù)據(jù)同步邻耕。
canal client HA
? ? 整體來說鸥咖,canal client的HA和canal server的HA機(jī)制是一模一樣的,它的實(shí)現(xiàn)邏輯其實(shí)在創(chuàng)建cluster client的時候用的封裝zookeeper的客戶端兄世,然后zookeeper的客戶端去檢測canal server節(jié)點(diǎn)內(nèi)容的變化并重新初始化連接而已啼辣。
說明
? ? 這個地方很明顯看出來,我們首先連接的zookeeper御滩,原因應(yīng)該很清楚鸥拧,因?yàn)槲覀冃枰獜膠ookeeper獲取提供服務(wù)的canal server的地址党远,在/otter/canal/destinations/destination/running節(jié)點(diǎn)去獲取。
說明
? ? 這部分其實(shí)就是client和zookeeper交互的部分富弦,負(fù)責(zé)實(shí)時感知節(jié)點(diǎn)變化并重新初始化連接沟娱,保證client端的HA。