1. 需求概述
業務開發中經常需要根據一些數據變更實現相對應的操作。例如,一些用戶注銷自己的賬戶,系統可以給用戶自動發短信確認,這時有兩種解決方案,一種是耦合到業務系統中,當用戶執行注銷操作的時候,執行發短信的操作,既是是通過MQ也是要耦合業務代碼的,第二種方案基于數據庫層面的操作,通過監聽binlog實現自動發短信操作,這樣就可以與業務系統解耦。
本示例主要基于mysql-binlog-connector實現對數據庫的監聽,并集成springboot的方案。
2. 技術選型
基于binlog實現數據同步的方案有兩種:
一種是mysql-binlog-connector,另一種是ali的canal。
mysql-binlog-connector:是通過引入依賴jar包實現,需要自行實現解析,但是相對輕量。
canal:是數據同步中間件,需要單獨部署維護,功能強大,支持數據庫及MQ的同步,維護成本高。
根據實際業務場景,按需索取,業務量小,業務簡單,輕量可以通過mysql-binlog-connector,業務量大,邏輯復雜,有專門的運維團隊,可以考慮canal,比較經過阿里高并發驗證,相對穩定。
3. 方案設計
1.支持對不同數據庫,不同表的配置監聽。
2.封裝細節數據庫,對外提供統一監聽。
3.講結果集封裝位方便操作數據結構。
5.講監聽信息統一放入阻塞隊列。
6.實現多線程消費。
4. 配置驗證
1、正常開啟狀態
mysql> show variables like 'log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin | ON |
+---------------+-------+
1 row in set (0.02 sec)
mysql> show binary logs;
+------------------+-----------+
| Log_name | File_size |
+------------------+-----------+
| mysql-bin.000001 | 154 |
+------------------+-----------+
1 row in set (0.09 sec)
2、權限不足情況
mysql> show binary logs;
1227 - Access denied; you need (at least one of) the SUPER, REPLICATION CLIENT privilege(s) for this operation
3、未開啟狀態(默認情況下是不開啟的)
mysql> show binary logs;
ERROR 1381 - You are not using binary logging
5. 代碼示例
詳見工程代碼:https://github.com/xzxiaoshan/mysql-binlog-demo
5.1. 事件中斷問題
當binlog服務上線之后,服務默認會在log文件的最新position處進行監聽。格式如下:
Connected to 192.168.10.220:3306 at test-bin.000557/270069874 (sid:65535, cid:1089065)
其中
test-bin.000557
是磁盤上的 binlog 文件名稱,270069874
是對應該 binlog 文件中的 position 位置。
但由于binlog服務下線,重新啟動后,默認又開始在最新position處進行監聽,會丟失一不分binlog的事件,所以每次事件均需要記錄當前的position位置。
當重新啟動服務時,使用記錄的position位置初始化BinaryLogClient。
注:單實例可以使用記錄到本地文件的方式存儲,如果需要考慮多實例分布式問題則需要考慮存儲到redis等共享存儲中。因為事件屬于高頻操作,所以建議使用redis或者MQ這種寫入速度較快的存儲方式。
5.2 文件輪換問題
當有人發出一個FLUSH LOGS
語句或者當前二進制日志文件變大超過max_binlog_size
時,binlog的文件名會重新一個新的文件,所以我們也要監聽ROTATE
事件并進行binlogFileName的記錄。
記錄binlogFileName和Position的代碼詳見文件
SaveBinlogFilenameAndPositionListener.java
(END)