(3)Canal高可用集群


1.前言

在最近項目開中,為了減少前台搜索對數據庫訪問壓力,入庫的物料都需要同步一份數據到ES,讓前台搜索直接訪問ES,不直接訪問數據庫獲取數據。一開始做法是代碼串行先保存到數據庫,再同步到ES。但是會有一個坑,如果兩者其一保存數據不成功,就會導致數據庫跟ES數據不一致,而且這種方式是對站點代碼是有侵入式的。搜索相關資料發現阿里的canal這個增量數據訂閱&消費的中間件可以無侵入式地有效解決該問題,canal偽造從庫拉取mysql庫每次修改binary log對象解析后,再通過MQ同步數據到ES。同時考慮系統健壯性,穩定性,所以把canal部署成高可用集群。

2. canal架構


我特定查閱官網資料幾遍,總體歸納canal架構如上幾種(如有錯誤,請各位看官指正,謝謝)。而這次功能重構,鑒於目前公司現有技術棧,決定采用架構圖③的架構進行重構。

2.1HA機制設計

canal的ha(雙機集群)分為兩部分,canal server和canal client分別有對應的ha實現:
●canal server:為了減少對mysql dump的請求,不同server上的實例(instance)要求同一時間只能有一個處於running,其他的處於standby狀態。
●canal client:為了保證有序性,一份實例(instance)同一時間只能由一個canal client進行get/ack/rollback操作,否則客戶端接收無法保證有序。
整個HA機制的控制主要是依賴了zookeeper的幾個特性,watcher和EPHEMERAL節點(和session生命周期綁定),后續我會繼續記錄zookeeper學習過程。
Canal Server HA架構原理:

流程步驟:
1.canal server要啟動某個canal instance時都先向zookeeper進行一次嘗試啟動判斷(實現:創建EPHEMERAL節點,誰創建成功就允許誰啟動)。
2.創建zookeeper節點成功后,對應的canal server就啟動對應的canal instance,沒有創建成功的canal instance就會處於standby狀態。
3.一旦zookeeper發現canal server A創建的節點消失后,立即通知其他的canal server再次進行步驟1的操作,重新選出一個canal server啟動instance。
4.canal client每次進行connect時,會首先向zookeeper詢問當前是誰啟動了canal instance,然后和其建立鏈接,一旦鏈接不可用,會重新嘗試connect。
注:canal client的方式和canal server方式類似,也是利用zookeeper的搶占EPHEMERAL節點的方式進行控制。

3.前期准備

3.1安裝zookeeper

可以參考我這篇“Zookeeper在linux環境中搭建集群”文章或者百度教程安裝。集群部署如下:

服務名稱

IP/域名

端口

zookeeper(slave)

192.168.142.129

2181

zookeeper(master)

192.168.142.130

2181

zookeeper(slave)

192.168.142.131

2181

3.2安裝mysql

可以參考我這篇”MySQL進階篇在linux環境下安裝” 文章或者百度教程安裝。MySQL我只部署單台:

服務名稱

IP/域名

端口

mysql

8.135.110.120(阿里雲)

3306

用戶名:canal,密碼:qwer1234

3.3安裝mq(因為我公司是使用RabbitMQ,所以安裝的是RabbitMQ)

可以參考我這篇“RabbitMQ在Docker上安裝”文章或者百度教程安裝。RabbitMQ我只部署單台:

服務名稱

IP/域名

端口

rabbitmq

8.135.110.120(阿里雲)

5672

管理后台登錄賬號:admin,密碼:qwer1234
再新建一個隊列用作演示:
Virtual hosts:/
交換器(Exchanges):canal.direct.test
路由key(Routing key):canal.routingkey.test
隊列(Queues):canal.queue.test

3.4安裝canal.server

可以參考我這篇“Canal入門”(這篇文章采用就是架構圖④的架構)或者百度教程安裝。集群部署如下:

服務名稱

IP/域名

端口

canal.server01

192.168.142.129

11110

canal.server02

192.168.142.130

11110

兩台canal.server實例我重新拷貝一份用作供應商報價業務,具體操作如下:

cp -r /home/deng/canal/canal.deployer/conf/example /home/deng/canal/canal.deployer/conf/quote_example

實例名稱:quote_example

3.5其他依賴

JDK版本:java version "1.8.0_311"

4.啟動canal集群

部署完canal.server兩個服務后,集群想要生效,還需要同時修改兩台服務的配置重新啟動才可以,具體操作如下:
●編輯vi conf/ canal.properties文件
因為canal.server集群需要zookeeper,所以在“common argument”標題下找到canal.zkServers選項修改為zookeeper集群地址;然后把canal.serverMode選項修改為rabbitMQ類型:

canal.zkServers = 192.168.142.129:2181,192.168.142.130:2181,192.168.142.131:2181
canal.serverMode = rabbitMQ

同時canal需要MQ進行同步數據,所以在“RabbitMQ” 標題下找到rabbitmq配置進行修改:

rabbitmq.host = 8.135.110.120
rabbitmq.virtual.host = /
rabbitmq.exchange = canal.direct.test
rabbitmq.username = admin
rabbitmq.password = qwer1234
rabbitmq.deliveryMode =

HA模式是依賴於instance name進行管理,必須都選擇default-instance.xml配置。在“destinations”標題下找到canal.instance.global.spring.xml選項進行啟用(其他兩個選項注釋):

canal.instance.global.spring.xml = classpath:spring/default-instance.xml

注:canal是允許配置多個實例(instance),假設每個canal.server服務都有相同的兩個實例(在conf目錄下分別建兩個實例文件夾:example1和example2,同時把默認實例example文件夾里的instance.properties文件拷貝一份過去),修改兩個實例canal.properties配置就能使其生效,在“destinations”標題下找到canal.destinations選項修改如下:

canal.destinations = example1, example2

●編輯vi conf/example/instance.properties文件(如果是多實例,則每個實例目錄下該文件都要修改配置,現在以canal.server01服務為例)

# mysql集群配置中的serverId概念,需要保證和當前mysql集群中id唯一
canal.instance.mysql.slaveId=129
# mysql數據庫連接地址和端口
canal.instance.master.address=8.135.110.120:3306
# mysql數據庫用戶名和密碼
canal.instance.dbUsername=canal
canal.instance.dbPassword=qwer1234
# mq配置(如果是沒用到MQ,則修改為實例名稱即可)
canal.mq.topic= example1
Or
# mq配置(如果是用到MQ,則修改為mq路由key)
canal.mq.topic=canal.routingkey.test

●啟動canal.server服務

cd /home/deng/canal/canal.deployer
sh bin/startup.sh


●登錄mysql增刪改一條數據(創建一個供應商報價supplier_quote臨時表)

INSERT ebs_material.supplier_quote (PN,Brand,StockQty) VALUES ('LM3585DT','TI',10000);
UPDATE ebs_material.supplier_quote SET Brand='TS1' WHERE Id=1;

在RabbitMQ管理后台隊列上會看到這兩條語句待消費消息:


下面再來驗證下canal集群是否成功。
●驗證canal集群是否成功
首先把canal.server01停止運行(也可以停止canal.server02運行,隨便一個都可以):

sh bin/stop.sh


查看日志:

從上述截圖可以看到129虛擬機canal.server01服務已經關閉了。現在在數據庫再插入一條報價數據:

INSERT ebs_material.supplier_quote (PN,Brand,StockQty) VALUES ('BAV999','TI',10000);

再查看下RabbitMQ管理后台隊列有沒有新增一條待消費的消息:


由此可見,已經新增一條待消費的消息,證明canal集群部署成功!

5.小結

在部署集群過程中偶爾會發生canal集群沒有推送MQ消費情況,需要重新啟動canal.server服務才生效,不知道是因為canal內部集成對rabbitmq不友好還是怎么的,后續測試排查下問題。該章節主要介紹如何搭建canal高可用集群,后續我們會深入了解內部原理跟其他功能。

參考文獻:
AdminGuide
簡介


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM