由 Canal 組件分析集成中間件架構的一般過程

  • 2019 年 10 月 6 日
  • 筆記

數據同步背景

為什麼要做數據同步?因為數據很多,還要共享或做它用。舉個栗子,你從移動硬碟拷貝一份小小電影到你的 Macbook 上賞析,也叫 數據同步。但系統不比你的單純,它使用的場景千奇百怪。數據同步,不管愛與不愛,你總會遇見,它會在某個時間等你,不離不棄,不見不散

哎,不就是 A 到 B 么,一個管道,罩得住。

Canal 簡介

要在有限的時間裡漂亮的完成工作,有時候你關注的並不一定是問題中心,深挖學習了 binlog的同步方式,並不會對你的工作進度有任何改善。將它加入到研究列表中,空閑的時間去學習更佳,沒必要非要把頭悶在水裡憋氣去體驗窒息的味道。好了,問題的中心數據同步,已經由阿里的工程師替你完成了,就叫 Canal,解決的是最常用的 MySQL資料庫同步到別處的問題。今天我們談一下 Canal 集成,但不談 Canal 細節實現。周邊建設別人不捨得告訴你,小姐姐和你聊。

Canal是將自己偽裝成一個 MySQL從庫從其他 真正的MySQL庫上拉取資訊,說白了就是實現了 MySQL的一套協議,數據拿過來之後,想怎麼把玩就怎麼玩嘍。東西是好東西,但 github上的 wiki文檔讓人看的昏昏欲睡,既然是談架構,那我們就聊一下如何才能讓工程師放心的使用 你的Canal

數據格式

簡單說下 Canal的數據格式,根據 github的官方文檔就能夠簡單的 RUN 起來。 Canal能夠同步大多數 DCLDMLDDL,我們通常也就關心 INSERTUPDATEDELETE引起的變化。那 Canal解釋的數據是什麼樣子呢,我們可以用一張圖來說明

可以看到 UPDATE同時包括 變更前變更後的值,需要的資訊就都有了。有了這些數據,上天入地,無所不能。

一個通用的架構模式就是只考慮輸入和輸出。使用者大多數並不關心你的系統是怎麼實現的,大家都很忙,而且並不一定都有興趣。他只需要你告訴他最終的使用方式和輸出格式即可。

整體高可用

那麼開發使用中有哪些元素需要參與呢?我們同樣上一張圖 (僅考慮集群主從模式,單機和 M/M不談)

很 Easy 是不是? ZK控制著 HA,同時記錄消費的消費進度,怎麼看都和 Kafka之流一個套路。但這裡有幾點要說明:

1) 為了保證 binlog正常拉取,Canal 伺服器同時只有一台工作,其他都是影子 lol 2) 為了保證消費能正常進行,Client 端同時只有一台能夠工作,其他都是影子 lol 3) binlog推薦使用 ROW模式,但有可能一個 update語句擠爆你的記憶體、打碎你的蛋蛋 4) Canal 本身沒有持久化能力,非常耗記憶體

我們接下來按照順序模擬它們的死亡。考慮下面一張圖。

紅色的區塊都是可能死亡的點,ZK 會死(當然它堅挺的很),MySQL 會死,至於 Canal,也肯定不能免俗,我們要讓它的死輕如鴻毛。

小姐姐,提醒,架構要考慮到每一個交互場景和極端情況。準備的越細,覺睡的越香。除了讓挑戰你的無聊者碰一鼻子灰(對,就是那些整天將 高可用掛在嘴上的貨),也能節省更多時間研究些更有意義的事情。

ZK 當機

ZooKeeper那麼健壯,為什麼還要模擬其當機呢?因為不排除 機房斷電的可能。為什麼我們首先談到 ZK?從圖中可以看到 Zk 死亡對系統的影響是巨大的。當然這僅僅是概率而已,最終會推斷出 SLA服務品質,滿足需求即可。

當然不排除有某些強迫症的外部因素影響你去做它的高可用。除了分機房,你 也可以在程式碼中進行集成,比如 ZK死亡,我們去直連 Canal。你要考慮開發成本和達到的效益是否合適。

有些公司在屁都沒做出來之前,就特別潔癖的關注低概率事件,問題本身倒成了次要的了。這種公司是有問題的,盡量去說服吧。

所以如果 ZK 當機問題佔用你的工作量,主要是其他人的認知問題。

Canal 當機

Canal集群模式已經通過 ZK 做了 HA,你要做的,就是模擬一遍。包括: 1) 當機一台,是否有其他實例頂上來 2) 全部當機,上線一台後是否能正常運行 3) 長時間下線後,突然上線是否有其他問題? 4) 記憶體問題。canal 非常耗記憶體,可以配置參數使其不溢出,但會產生阻塞。

Client 當機

Client 的當機其實是無所謂的。但由於實現的方式千奇百怪,也會產生千奇百怪的事情。本部分主要是使用方式問題,可以備註在注意事項里。我們通過程式碼來說明

1) 程式碼有兩層 while循環,如果只有一層的話,會出問題的 (想一想問什麼) 2) 程式碼有 ACK確認機制,程式碼顯示的進行了確認和回滾。但如果你的處理是放在多執行緒里,那就有可能漏掉消息 3) 消息有 batch,所以不可避免會出現重複消費的情況,你的業務支援冪等么?

MySQL 當機

1) MySQL 重新上線後 Canal 是否能夠正常拉取 binlog? 2) 主從切換後,是否需要修改 Canal? 怎麼補數據?

外圍擴展

要將 Canal 用起來的話,它本身只能算是一個 半成品。只有給它加上翅膀,它才能夠自由飛翔。

MQ

考慮到 Canal 的堆積能力並不強。堆積數據到 10W+時,速度會變慢,並會出現假死現象。另外一個場景,就是 canal 突然上線,這時候已經延後 binlog 很多了,重新連接後會一次性獲取所有數據,卡到死為止~。

對於第一個場景,一個 MQ 介入是非常有必要的。Kafka 等消息隊列的堆積能力已經家喻戶曉,我們要做的就是將 Canal 的數據進行一次轉發。以後的客戶端,打交道的就只有 MQ 了。MQ 介入後,有以下好處:

1) 獲得非常好的堆積能力,可以延後消費 2) 能夠方便的得到積壓數據,進行監控報警 3) 不比引入 Canal 客戶端,客戶端開發只與 MQ 打交道即可 4) MQ 支援順序消息,對於無時序數據而言,非順序消息能增加處理能力

監控報警

每個節點都會出問題,所以每個節點都需要監控。監控系統也是每個公司的工具鏈,你可能需要寫一些 zabbix或者 telegraf腳本進行數據收集(監控系統我們後續文章介紹)。

進程監控

監控各組件是否存活,java 程式發生記憶體溢出死亡的概率還是很大的。如果想要進程死亡後自動重啟,可以考慮採用 supervisor組件。

BTW:如果你找不到進程的死亡原因,執行 dmesg命令,大概率會看到死亡原因。

業務監控

1) MySQL binlog 位置監控( show master status;)。 2) Canal 到 MQ 的 Sink 消費位點監控。 3) 業務消費端對於 MQ 的消費延遲監控 (delay)。

自動部署

一個好的持續集成工具能夠大量減少上線時間和故障響應時間。此部分與各公司的工具鏈有關。比如可以使用 ansible 等命令行工具,也可以使用 jenkins 等。

這部分的工作量還是比較大的,尤其是當組件增多。有幾個容易忽略的點需要考慮: 1) MySQL 主從切換時,Canal 的配置是否需要變動 2) 當單 MySQL 實例庫表過多時,Canal 是否需要分開部署,維護其拓撲結構 3) 各組件啟動順序問題,是否程式碼做了兼容能夠支援 4) 數據同步需求是否線性增長,對應 Topic 的粒度支援

迭代思路

一個使用了第三方組件的數據同步中間件產品的建設過程,大體是分為以下 6 個階段的。很多人還停留在搭起來就 OK 的階段。除了搭建驗證讀源碼或者是自己造輪子,還有很多額外的事情要做,這才是架構師應該關注的事情。

基礎搭建使用

可以根據文檔完成一個 quickstart,並能初步應用到業務中。此時的服務基本上是裸跑,有比較多的風險。

API 封裝易用

根據自己的使用場景剔除或者增加部分功能,根據自己公司的編碼和程式碼風格,編寫訂製易用的 API。這可能是一個適配器,也可能是一個 spring-starter 等。還有一些坑需要進行屏蔽等,比如開源版本的 Canal 沒有 GTID 等,呵呵。這個時候適當讀下源碼是非常有必要的。

整體高可用和應急方案

對於一個重量級的中間產品,此部分的重要度是不言而喻的。數據交互節點,每一個都應該是不信任的。仔細 CHECK 數據交互中的每一個節點,找出突發情況的應急方案。有條件的,需要線上反覆演練,確保系統整體達到高可用。

報警運維機制

完成責任劃分和應急處理人員,確保每一條報警資訊都能快速響應,將故障影響面降低到最低。此部分涉及流程機制問題,作為架構師是有責任推進其完成的。

內部文檔與系統集成

為了達到快速響應的目的,同時讓產品更加平滑的加入到公司技術棧中,需要將其集成到公司內部系統中。比如訂製的監控系統、持續集成系統等。同時,為了減少其他夥伴的學習使用成本,一個淺顯易懂的文檔也是必要的(不是 doc 哦)。對於使用中容易造成故障的點,也要指出,並不是每個人都和你一樣聰明能幹。

宣傳應用檢驗階段

如果對你的系統有信心,最大規模的使用去檢驗其魯棒性是極好的。一些宣傳和支援是必要的,相信到了此階段,有大量的使用案例,不斷的培養用戶,對你系統的懷疑會不攻自破。

總結

架構只是做技術么?這是狹義上的理解,技術是個敲門磚。廣義上的架構包括技術、流程和人。轉變這個觀念,願你的事業更上一層樓。