Debezium的MySQL連接器的工作原理

原文參考官網:https://debezium.io/docs/connectors/mysql/#collapse4

       本文將深入Debezium的MySQL連接器(一種kafka connector)的工作細節,包括跟蹤表結構(structure of tables)、執行快照任務、把binlog事件轉換成記錄在Kafka中的Debezium的更改事件、故障發生時連接器的行爲。

數據庫模式歷史(Database schema history)

       當數據庫客戶端查詢數據庫的時候,它使用的是數據庫當前的模式(schema)。然而,數據庫schema隨時可能改變,這意味這,MySQL連接器(connector)必須知道在每個insert,update或者delete操作被記錄時數據庫的schema是什麼樣的。MySQL連接器不能只使用當前的數據庫schema,因爲它可能處理的事件是老的事件,在表schema更改前就記錄的事件(即不能用新的表schema來處理舊的表schema對應的binlog事件)。幸運的是,MySQL在binlog中包含了數據的行級別改變(row-level change),也包含了對數據庫的DDL(包括create、alter、drop等)操作。當MySQL連接器讀取binlog的時候,遇到了DDL語句時,連接器會更新內存中的每個表的schema表示(representation of table’s schema),這個schema表示將用於理解後續的每個insert,update,或者delete操作發生時的表結構(structure),從而產生合理的改變事件(change event)。連接器也在一個單獨的Kafka topic(即的數據庫歷史topic)中記錄了DDL的語句和DDL語句所在的binlog日誌位置。
       當連接器崩潰或者正常停止後再重啓時,連接器將從binlog的特定位置(比如特定的時間點)開始讀。連接器將通過讀取Kafka的數據庫歷史topic,解析所有的DDL語句,一直到連接器重啓時讀取binlog的位置,以此重新構建此時的表結構(structure)。
       數據庫歷史topic只給連接器用的,但是連接器可以選擇在另一個kafka topic上生產模式改變事件(schema change events),專門給消費者應用使用。(在數據庫模式(schema)歷史中,保證事件的全局順序是很重要的,所以數據庫歷史topic不能分區,這意味着,創建這個topic的時候必須指定分區數爲1。當依賴kafka自動創建topic的機制時,要保證配置選項中的默認分區數num.partitions被設置成1)。

快照(Snapshots)

       在connector的配置中,用snapshot.mode配置項表示快照模式。
       當一個被設置成一個MySQL服務器實例跟從者的MySQL連接器啓動的時候,它會默認執行一次數據庫初始的一致性快照任務。這是默認的initial模式(mode),因爲大多數情況下,MySQL的binlog不再包含數據庫的完整歷史操作(爲了節省磁盤空間,MySQL只會記錄一定時間內或者一定大小的binlog)。
MySQL連接器每次獲取快照的時候會執行以下的步驟:
1. 獲取一個全局讀鎖,從而阻塞住其他數據庫客戶端的寫操作。
2. 開啓一個可重複讀語義的事務,來保證後續的在同一個事務內讀操作都是在一個一致性快照中完成的。
3. 讀取binlog的當前位置。
4. 讀取連接器中配置的數據庫和表的模式(schema)信息。
5. 釋放全局讀鎖,允許其他的數據庫客戶端對數據庫進行寫操作。
6. (可選)把DDL改變事件寫入模式改變topic(schema change topic),包括所有的必要的DROPCREATEDDL語句。
7. 掃描所有數據庫的表,並且爲每一個表產生一個和特定表相關的kafka topic創建事件(即爲每一個表創建一個kafka topic)。
8. 提交事務。
9. 記錄連接器成功完成快照任務時的連接器偏移量。

       步驟1獲取全局讀鎖的目的在於防止連接器在讀取binlog和表schema信息的時候別的數據庫客戶端進行DDL操作帶來的干擾,從步驟1獲取鎖到步驟5釋放鎖的時間是很短的,所以對數據庫的影響很小。
       如果連接器失敗了,或者被再平衡(rebalanced),或者在快照沒完成前掛掉了,連接器將在重啓的時候開啓一個新的快照。一旦連接器完成了初始快照,連接器就會從步驟3中讀取的binlog位置開始繼續讀下去,以確保連接器不再丟失任何更新。如果連接器因爲某種原因又掛了,下次重啓的時候就會從上次停止的地方接着讀。然而,如果連接器停止了很長時間,MySQL可能把老的binlog清理了,連接器上次讀取的binlog位置就可能丟失了。在這種情況下,當配置了initial快照模式(默認的mode)的連接器很長時間後重啓的時候,MySQL的服務器已經沒有連接器要讀取的binlog位置,連接器就會報錯停止。
       第二種快照模式(snapshot mode)when_needed允許連接器在有必要的任何時候執行快照任務。這個和上面提到的默認的initial快照相似,唯一不同的是:如果連接器重啓並且MySQL不再有連接器啓動時讀取的binlog位置,連接器將執行另一次快照任務而不是失敗。這種模式也許是最自動化的,但是在遇到故障時(通常指連接器掛掉很長時間)存在執行額外快照的風險。
       第三種快照模式never,保證了連接器從不執行快照任務。當一個新的連接器配置成這種模式的時候,它會從binlog的起始位置開始讀。這不是默認的行爲,因爲這種模式的連接器(沒有快照)要求MySQL的binlog包含連接器所監控的數據庫的所有歷史,通常MySQL實例不會這麼配置,即不會保存所有歷史的binlog。特別地,binlog必須包含連接器監控的每個表的至少CREATE TABLE語句。如果這個要求不能滿足,連接器將不能合理解釋binlog中的行級別事件的結構信息,這樣連接器就會簡單粗暴地跳過所有丟失表定義的事件。(連接器不能依賴表的當前schema信息,因爲表可能會在binlog中記錄初始事件後被改變(alter),連接器沒辦法根據當前的schema合理解釋binlog中的事件)
       從Debezium 0.3.4版本開始,第四種快照模式schema_only出現了,它允許連接器啓動後從它當前所在MySQL binlog位置開始讀。通過schema_only模式,連接器從當前binlog位置開始讀,捕獲當前表的schema信息,不讀取任何數據信息,然後從當前位置開始繼續讀取binlog。這樣導致改變事件流(change event stream)只包括快照開始後發生的改變事件。這種模式對於那些不需要知道數據庫完整狀態,只想知道連接器啓動後的改變的消費者很有用。
       從Debezium 0.7.2開始,第五種快照模式schema_only_recovery,允許一個存在的連接器去恢復中斷的或者丟失的數據庫歷史topic。它和schema_only模式很像,它也不讀取任何數據信息,只捕獲當前表schema信息。不同的地方在於:

  • 它只可以被用在已經存在的連接器上,作爲對連接器配置的更新項。
  • 它從已經存在的連接器上次提交的binlog位置開始讀起,而不是binlog的當前位置。

       schema_only_recovery也可以被用於定期清理數據庫歷史topic(這個topic需要無限期留存kafka日誌),如果不定期清理,這個topic的數據可能會不受控制地增長。爲了做到定期清理,在把連接器快照模式改成schema_only_recovery模式之前,必須手動刪除數據庫歷史topic。注意,這種模式只有在上次連接器提交偏移量後沒有schema變化。否則,在連接器提交的偏移量和schema發生變化的binlog位置之間的binlog事件就會在不一致的schema中被髮送出去(已經基於改變後的schema,還沒有爲之前的事件應用的schema)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章