首先看一下canal的實現原理:
- canal 模擬 MySQL slave 的交互協議,僞裝自己爲 MySQL slave ,向 MySQL master 發送dump 協議
- MySQL master 收到 dump 請求,開始推送 binary log 給 slave (即 canal )
- canal 解析 binary log 對象(原始爲 byte 流)
怎麼使用?
這裏只記錄需要使用過程中需要注意的地方,具體用法不在此贅述,可以參考canal的wiki:https://github.com/alibaba/canal
一、數據庫配置:
- 需要先開啓 Binlog 寫入功能,配置 binlog-format 爲 ROW 模式,my.cnf 中配置如下
|
- 授權 canal 鏈接 MySQL 賬號具有作爲 MySQL slave 的權限, 如果已有賬戶可直接 grant
|
二、canal server端:
1. conf/canal.properties下修改端口
2. 可以配置destinations(默認爲example,多個以逗號隔開),這個對應conf下面的文件夾order
3. order文件夾中的instance.properties,可以進行消費通道的配置:
三、canal client端:
canal 1.1.1版本之後,自帶了適配器,不用寫任何java代碼,只需要寫幾個SQL腳本就可以直接實現同步,簡單同步邏輯的可以考慮使用,比如單表同步、多表簡單關聯,友情提醒請看文章末尾。
canal adapter 的 Elasticsearch 版本支持6.x.x以上,但是目前公司使用的es爲5.3.3,官方宣稱可以通過更改依賴即可適配低版本的es,但是還有一個地方需要調整,具體改動如下:
- 先將client-adapter中elasticsearch下的pom文件中依賴的elasticsearch相關組件的版本號降至5.X
-
com.alibaba.otter.canal.client.adapter.es.ESAdapter類中
transportClient.addTransportAddress(
new
TransportAddress(InetAddress.getByName(host.substring(
0
, i)),
Integer.parseInt(host.substring(i +
1
))));
修改成:
transportClient.addTransportAddress(
new
InetSocketTransportAddress(InetAddress.getByName(host.substring(
0
, i)),
Integer.parseInt(host.substring(i +
1
))));
3. 重新編譯
mvn clean install -Dmaven.test.skip -Denv=release
另外在同步SQL上面也有很多限制,下面是官方文檔的:
- 主表不能爲子查詢語句
- 只能使用left outer join即最左表一定要是主表
- 關聯從表如果是子查詢不能有多張表
- 主sql中不能有where查詢條件(從表子查詢中可以有where條件但是不推薦, 可能會造成數據同步的不一致, 比如修改了where條件中的字段內容)
- 關聯條件只允許主外鍵的'='操作不能出現其他常量判斷比如: on a.role_id=b.id and b.statues=1
- 關聯條件必須要有一個字段出現在主查詢語句中比如: on a.role_id=b.id 其中的 a.role_id 或者 b.id 必須出現在主select語句中
除此之外,在使用過程中,還發現了一些其它未說明的限制和問題
1. _index只支持索引名稱,不支持alias,在索引需要重構修改名稱的時候,這裏也需要進行修改。
2. 查詢語句的字段大小寫必須跟數據庫中一致,如圖中的ORDER_ID,如不指定,不會報錯,但是查不出數據。
3. 在某一個表的數據時,會刪除整個文檔,比如刪除了order_payment,那麼會整個order_header文檔。
5. 更新時查詢不支持非數字類型主鍵,這個是由於拼接SQL字符串導致,已通過修改拼接代碼解決。
6. 有一種業務場景,就是修改供應商或者維修廠的名稱時,會涉及大量的文檔更新,看了下原來的代碼的代碼中使用了批處理,但是速度奇慢,後續把代碼註釋掉之後,速度卻得到了質的提升,無解。
注意:
對於官方提供的canal adapter,個人建議酌情使用,在非常簡單的單表同步或者多表簡單關聯,可以考慮使用,能夠很大程度的節省開發時間
在訂單查詢優化過程中,早期一直在使用canal adapter,但是因爲訂單的業務同步關聯比較複雜,在對源碼進行了多次修改才適配了訂單數據的同步,另外,canal adapter在大多數場景下都會進行回表查詢,這對同步效率也會有一定的影響。
在後面演示環境的DTS數據訂閱處理時,發現有些代碼完全可以爲測試環境的canal同步所用,考慮到後續同步的靈活性,決定放棄了官方的adapter,自己寫一套adapter。