MySQL實時同步到Elasticsearch實現方案 —— canal(兼容ES5.X)

首先看一下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 中配置如下

log-bin=mysql-bin # 開啓 binlog

 

binlog-format=ROW # 選擇 ROW 模式 server_id=1 # 配置 MySQL replaction 需要定義,不要和 canal 的 slaveId 重複

  • 授權 canal 鏈接 MySQL 賬號具有作爲 MySQL slave 的權限, 如果已有賬戶可直接 grant

CREATE USER canal IDENTIFIED BY 'canal'

GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%';

-- GRANT ALL PRIVILEGES ON *.* TO 'canal'@'%' ;

FLUSH PRIVILEGES;

二、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,但是還有一個地方需要調整,具體改動如下:

  1. 先將client-adapter中elasticsearch下的pom文件中依賴的elasticsearch相關組件的版本號降至5.X
  2. 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上面也有很多限制,下面是官方文檔的:

  1. 主表不能爲子查詢語句
  2. 只能使用left outer join即最左表一定要是主表
  3. 關聯從表如果是子查詢不能有多張表
  4. 主sql中不能有where查詢條件(從表子查詢中可以有where條件但是不推薦, 可能會造成數據同步的不一致, 比如修改了where條件中的字段內容)
  5. 關聯條件只允許主外鍵的'='操作不能出現其他常量判斷比如: on a.role_id=b.id and b.statues=1
  6. 關聯條件必須要有一個字段出現在主查詢語句中比如: 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。

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