日常的使用中,當使用 ZooKeeper 作爲高可用方案時,因某些原因需要重新採集數據,只要目標庫中的 binlog 文件依舊存在,那麼就能夠將 Canal 的解析位置重新定位,從指定的位置開始解析。
Canal 默認在 ZooKeeper 中存儲的節點爲:
/otter/canal
一、停止 Canal 服務
在有數據被消費時,客戶端的每次 Ack 都會使得服務端用本地緩存的位點信息去覆蓋 ZooKeeper 上的位點,所以在修改 ZooKeeper 的位點之前,應先避免其不再被覆蓋,即停止 Canal 服務。
亦可停止該 instance 對應的消費端程序,則不會再觸發服務端使用緩存中的位點信息去覆蓋 ZooKeeper 中的信息。
二、獲取位點信息
停止服務後,可通過 zkCli.sh、ZooInspector、zkui 等工具連接到相應的 ZooKeeper 服務器上,並獲取到當前的位點信息。
默認情況下,位點信息存儲在下述節點中:
/otter/canal/destinations/${destination}/1001/cursor
注意:請將 ${destination} 替換成預期的 instance 名稱。
若 ZooKeeper 中並無 …/1001/cursor 節點,則表明該 instance 從未被消費過,可通過啓動一次對應的消費者,以生成該位點信息,但記得生成位點信息後要將其停止。
本文僅以 zkCli.sh 方式示例如何獲取名爲 “example” 的 instance 的位點信息:
get /otter/canal/destinations/example/1001/cursor
獲取到的位點信息結果爲:
{"@type":"com.alibaba.otter.canal.protocol.position.LogPosition","identity":{"slaveId":-1,"sourceAddress":{"address":"localhost","port":3306}},"postion":{"gtid":"","included":false,"journalName":"mysql-bin.000010","position":210013,"serverId":1,"timestamp":1590112037000}}
從上述的結果可看出,位點信息是用 json 格式的字符串進行存儲的,裏面存放了許多信息,我們僅需要變更“journalName”和“position”兩個屬性值,分別對應當前的 binlog 文件名以及該文件內的具體位置。
三、查詢數據庫位點
我們既然已經確定了變更位點需要哪些信息,那麼又如何獲得預期的位點信息呢?這就需要視需求而定了,其實,一般來變更位點都是往當前位置的前面調整,再次採集已同步過的數據。本文僅給出如何在 MySQL 中通過 SQL 語句查詢 binlog 的位點信息示例:
-
查詢 binlog 文件
show binary logs
上述命令用於列出該 MySQL 服務當前有效的二進制日誌文件信息,具體輸出內容如下:
Log_name File_size mysql-bin.000001 52302 mysql-bin.000002 16902 mysql-bin.000003 49094 mysql-bin.000004 130772 mysql-bin.000005 3492 此處的輸出結果僅爲 binlog 文件名稱和大小,該如何確定具體的該使用哪個文件的哪個位置呢?請稍安勿躁,此步驟僅是爲了下一步作鋪墊。
-
查詢 binlog 事件
binary log,顧名思義就是二進制日誌文件,裏面存放的信息無法直接被展示出來,但我們可以通過 MySQL 的 SQL 語句將其解析成對應的事件,通過判斷事件來找出對應的位點信息。
用於查詢 binlog 事件的 SQL 語法如下:show binlog events [in 'binlog_name'] [from pos] [limit [offset,] row_count]
在查詢 binlog 事件時,強烈建議儘可能多地增加限制結果集大小的條件,以降低對 MySQL 的性能損耗,這就是有1. 查詢 binlog 文件步驟的原因,爲此步驟提供信息。
下述示例表示列出名爲“mysql-bin.000008”的文件內從第 4 個位點開始往後的 5 條記錄。
show binlog events in 'mysql-bin.000008' from 4 limit 5
輸出的結果爲:
Log_name Pos Event_Type Server_id End_log_pos Info mysql-bin.000008 4 Format_desc 1 123 Server ver: 5.7.27-log, Binlog ver: 4 mysql-bin.000008 123 Previous_gtids 1 154 mysql-bin.000008 154 Anonymous_Gtid 1 219 SET @@SESSION.GTID_NEXT= ‘ANONYMOUS’ mysql-bin.000008 219 Query 1 292 BEGIN mysql-bin.000008 292 Table_map 1 351 table_id: 109 (test2.user_info) 當前僅能通過判斷具體的事件,來確定對應的位點值(Pos)。
四、變更位點信息
假設我們需要的目標位點信息是:名爲 mysql-bin.000008 的日誌文件內位點值爲 4。那麼通過 zkCli.sh 的 set 方法進行變更,示例如下:
set /otter/canal/destinations/example/1001/cursor {"@type":"com.alibaba.otter.canal.protocol.position.LogPosition","identity":{"slaveId":-1,"sourceAddress":{"address":"localhost","port":3306}},"postion":{"gtid":"","included":false,"journalName":"mysql-bin.000008","position":4,"serverId":1,"timestamp":1590112037000}}
注意:節點名與節點值之間使用一個半角空格進行分隔。
五、啓動 Canal 服務
啓動 Canal 服務端,以使新的位點生效。
如果之前通過停止消費端的方式來消除位點被覆蓋,那麼此時就需要通過重啓 Canal 服務端將 ZooKeeper 上新的位點信息去覆蓋 Canal 服務端緩存中的信息。