一、前言
Canal
是阿里的一款開源專案,純 Java
開發。基於資料庫增量日誌解析,提供增量資料訂閱&消費,目前主要支援了 MySQL
(也支援 mariaDB
)。
Canal
除了支援 binlog
實時 增量同步 資料庫之外也支援 全量同步 ,本文主要分享使用Canal來實現從MySQL到Elasticsearch的全量同步;
可通過使用 adapter
的 REST
介面手動觸發 ETL
任務,實現全量同步。
在執行全量同步的時候,同一個
destination
的增量同步任務會被 阻塞,待全量同步完成被阻塞的增量同步會被 重新喚醒
PS:關於Canal的部署與 實時同步 請看文章《Canal高可用架構部署》
二、ETL介面
adapter
的 ETL
介面為:/etl/{type}/{task}
- 預設web埠為
8081
- type 為型別(hbase/es7/rdb)
- task 為任務名對應配置檔名,如sys_user.yml
例子:
curl -X POST http://127.0.0.1:8081/etl/es7/sys_user.yml
執行成功輸出:
{"succeeded":true,"resultMessage":"匯入ES 資料:17 條"}
三、實踐過程中遇到的坑
3.1. 連線池不夠
當同步的資料量比較大時,執行一段時間後會出現下圖的錯誤
3.1.1. 原因分析
檢視 canal
原始碼得知當同步的資料量大於1w時,會分批進行同步,每批1w條記錄,並使用多執行緒來並行執行任務,而 adapter
預設的連線池為3,當執行緒獲取資料庫連線等待超過1分鐘就會丟擲該異常。
執行緒數為當前伺服器cpu的可用執行緒數
3.1.2. 解決方式
修改 adapter
的 conf/application.yml
檔案中的 srcDataSources
配置項,增加 maxActive
配置資料庫的最大連線數為當前伺服器cpu的可用執行緒數
cpu執行緒數可以下命令檢視
grep 'processor' /proc/cpuinfo | sort -u | wc -l
3.2. es連線超時
當同步的表欄位比較多時,機率出現以下報錯
3.2.1. 原因分析
由於 adapter
的表對映配置檔案中的 commitBatch
提交批大小設定過大導致(6000)
3.2.2. 解決方式
修改 adapter
的 conf/es7/xxx.yml
對映檔案中的 commitBatch
配置項為3000
3.3. 同步慢
三千萬的資料量用時3.5小時左右
3.3.1. 原因分析
由於當資料量大於1w時 canal
會對資料進行分批同步,每批1w條通過分頁查詢實現;所以當資料量較大時會出現深分頁的情況導致查詢非常慢。
3.3.2. 解決方式
預先使用ID、時間或者業務欄位等進行資料分批後再進行同步,減少每次同步的資料量。
3.3.3. 案例
使用ID進行資料分批,適合增長型別的ID,如自增ID、雪花ID等;
- 查出 最小ID、最大ID 與 總資料量
- 根據每批資料量大小計算每批的 ID區間
計算過程:
- 最小ID = 1333224842416979257
- 最大ID = 1341698897306914816
- 總資料量 = 3kw
- 每次同步量 = 300w
(1) 計算同步的次數
總資料量 / 每次同步量 = 10
(2) 計算每批ID的增量值
(最大ID - 最小ID) / 次數 = 847405488993555.9
(3) 計算每批ID的值
最小ID + 增量值 = ID2
ID2 + 增量值 = ID3
...
ID9 + 增量值 = 最大ID
(4) 使用分批的ID值進行同步
修改sql對映配置,的 etlCondition
引數:
etlCondition: "where id >= {} and id < {}"
呼叫etl介面,並增加 params
引數,多個引數之間使用 ;
分割
curl -X POST http://127.0.0.1:8081/etl/es7/sys_user.yml?params=最小ID;ID2
curl -X POST http://127.0.0.1:8081/etl/es7/sys_user.yml?params=ID2;ID3
...