Canal高可用架構部署
一、前言
canal
是阿里的一款開源項目,純 Java
開發。基於數據庫增量日誌解析,提供增量數據訂閲&消費,目前主要支持了 MySQL
(也支持 mariaDB
)。
- canal 模擬 mysql slave 的交互協議,偽裝自己為 mysql slave,向 mysql master發送 dump 協議;
- mysql master 收到 dump 請求,開始推送binary log給 slave(也就是canal)
- canal 解析 binary log對象(原始為byte流)。
總體架構:
二、部署準備
下載地址: https://github.com/alibaba/canal/releases
分別下載:canal.admin、canal.deployer、canal.adapter
PS:只有1.1.5以上版本才支持es7.x
其他依賴:
- JDK1.8
- MySQL:用於canal-admin存儲配置和節點等相關數據
- Zookeeper
三、HA機制
整個 HA 機制的控制主要是依賴了zookeeper的兩個特性:watcher、EPHEMERAL節點。canal的 HA 機制實現分為兩部分,canal server 和 canal client分別有對應的實現。
canal server實現流程如下:
- canal server 要啟動某個 canal instance 時都先向 zookeeper 進行一次嘗試啟動判斷 (實現:創建 EPHEMERAL 節點,誰創建成功就允許誰啟動);
- 創建 zookeeper 節點成功後,對應的 canal server 就啟動對應的 canal instance,沒有創建成功的 canal instance 就會處於 standby 狀態;
- 一旦 zookeeper 發現 canal server A 創建的節點消失後,立即通知其他的 canal server 再次進行步驟1的操作,重新選出一個 canal server 啟動instance;
- canal client 每次進行connect時,會首先向 zookeeper 詢問當前是誰啟動了canal instance,然後和其建立鏈接,一旦鏈接不可用,會重新嘗試connect。
PS: 為了減少對mysql dump的請求,不同server上的instance要求同一時間只能有一個處於running,其他的處於standby狀態。
canal client實現流程
- canal client 的方式和 canal server 方式類似,也是利用 zookeeper 的搶佔EPHEMERAL 節點的方式進行控制
- 為了保證有序性,一份 instance 同一時間只能由一個 canal client 進行get/ack/rollback操作,否則客户端接收無法保證有序。
四、集羣部署
4.1. MySQL準備
4.1.1. 開啟binlog
MySQL的 my.cnf
中配置如下
[mysqld]
log-bin=mysql-bin # 開啟 binlog
binlog-format=ROW # 選擇 ROW 模式
server_id=1 # 配置 MySQL replaction 需要定義,不要和 canal 的 slaveId 重複
注意:如果訂閲的是mysql的從庫,需求增加配置讓從庫日誌也寫到binlog裏面
log_slave_updates=1
可以通過在 mysql 終端中執行以下命令判斷配置是否生效:
show variables like 'log_bin';
show variables like 'binlog_format';
4.1.2. 授權賬號權限
授權 canal 鏈接 MySQL 賬號具有作為 MySQL slave 的權限, 如果已有賬户可直接 grant:
CREATE USER canal IDENTIFIED BY 'canal';
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%';
FLUSH PRIVILEGES;
4.2. 部署canal-admin
4.2.1. 作用
- 通過圖形化界面管理配置參數。
- 動態啟停
Server
和Instance
- 查看日誌信息
4.2.2. 執行數據庫腳本
執行 conf
目錄下載的 canal_manager.sql
腳步,初始化所需的庫表。
初始化SQL腳本里會默認創建canal_manager的數據庫,建議使用root等有超級權限的賬號進行初始化
4.2.3. 配置修改
執行 vim conf/application.yml
server:
port: 8089
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
spring.datasource:
address: 127.0.0.1:3306
database: canal_manager
username: canal
password: canal
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://${spring.datasource.address}/${spring.datasource.database}?useUnicode=true&characterEncoding=UTF-8&useSSL=false
hikari:
maximum-pool-size: 30
minimum-idle: 1
canal:
adminUser: admin
adminPasswd: admin
修改
address
、database
、username
、password
四個參數
4.2.4. 啟停命令
啟動
sh bin/startup.sh
停止
sh bin/stop.sh
4.2.5. 使用
通過 http://127.0.0.1:8089/ 訪問,默認密碼:admin/123456
4.2.5.1. 創建集羣
配置 集羣名稱 與 ZK地址
配置 主配置,該配置為集羣內的所有Server實例共享的 主要修改以下配置:
- canal.zkServers 配置zookeeper集羣地址
- canal.instance.global.spring.xml 改為classpath:spring/default-instance.xml
4.2.5.2. 創建Server
配置項:
- 所屬集羣,可以選擇為單機 或者 集羣。一般單機Server的模式主要用於一次性的任務或者測試任務
- Server名稱,唯一即可,方便自己記憶
- Server Ip,機器ip
- admin端口,canal 1.1.4版本新增的能力,會在canal-server上提供遠程管理操作,默認值11110
- tcp端口,canal提供netty數據訂閲服務的端口
- metric端口, promethues的exporter監控數據端口 (未來會對接監控)
多台Server關聯同一個集羣即可形成主備HA架構
4.2.5.3. 創建Instance
每個 Instance
關聯一個同步的數據源,如果有多個數據源需要同步則需要創建多個 實例
- 先填寫實例名
- 選擇剛剛創建的集羣
- 載入模板配置
主要修改以下配置:
- canal.instance.master.address 配置要同步的數據庫地址
- canal.instance.dbUsername 數據庫用户名(需同步權限)
- canal.instance.dbPassword 數據庫密碼
- canal.instance.filter.regex mysql 數據解析關注的表,Perl正則表達式.多個正則之間以逗號(,)分隔,轉義符需要雙斜槓(\)
canal.instance.filter.regex常見例子:
- 所有表:.* or .\..
- canal schema下所有表: canal\..*
- canal下的以canal打頭的表:canal\.canal.*
- canal schema下的一張表:canal.test1
- 多個規則組合使用:canal\..*,mysql.test1,mysql.test2 (逗號分隔) 注意:此過濾條件只針對row模式的數據有效(ps. mixed/statement因為不解析sql,所以無法準確提取tableName進行過濾)
4.3. 部署canal-deployer
4.3.1. 作用
- 偽裝成
MySQL
的從庫,同步主庫的binlog日誌。 - 解析並結構化
binary log
對象。
4.3.2. 修改配置
執行 vim conf/canal_local.properties
修改配置項 canal.admin.manager
為canal-admin的地址
4.3.3. 啟停命令
使用 local 配置啟動
bin/startup.sh local
停止
bin/stop.sh
4.4. 部署canal-adapter
4.4.1. 作用
- 對接上游消息,包括kafka、rocketmq、canal-server
- 實現mysql數據的增量同步
- 實現mysql數據的全量同步
- 下游寫入支持mysql、es、hbase等
4.4.2. 修改配置
注意:目前
adapter
是支持動態配置的,也就是説修改配置文件後無需重啟,任務會自動刷新配置!
(1) 修改application.yml
執行 vim conf/application.yml
修改consumerProperties、srcDataSources、canalAdapters的配置
canal.conf:
mode: tcp # kafka rocketMQ # canal client的模式: tcp kafka rocketMQ
flatMessage: true # 扁平message開關, 是否以json字符串形式投遞數據, 僅在kafka/rocketMQ模式下有效
syncBatchSize: 1000 # 每次同步的批數量
retries: 0 # 重試次數, -1為無限重試
timeout: # 同步超時時間, 單位毫秒
consumerProperties:
canal.tcp.server.host: # 對應單機模式下的canal
canal.tcp.zookeeper.hosts: 127.0.0.1:2181 # 對應集羣模式下的zk地址, 如果配置了canal.tcp.server.host, 則以canal.tcp.server.host為準
canal.tcp.batch.size: 500 # tcp每次拉取消息的數量
srcDataSources: # 源數據庫
defaultDS: # 自定義名稱
url: jdbc:mysql://127.0.0.1:3306/mytest?useUnicode=true # jdbc url
username: root # jdbc 賬號
password: 121212 # jdbc 密碼
canalAdapters: # 適配器列表
- instance: example # canal 實例名或者 MQ topic 名
groups: # 分組列表
- groupId: g1 # 分組id, 如果是MQ模式將用到該值
outerAdapters: # 分組內適配器列表
- name: es7 # es7適配器
mode: rest # transport or rest
hosts: 127.0.0.1:9200 # es地址
security.auth: test:123456 # 訪問es的認證信息,如沒有則不需要填
cluster.name: my-es # 集羣名稱,transport模式必需配置
......
- 一份數據可以被多個group同時消費, 多個group之間會是一個並行執行, 一個group內部是一個串行執行多個outerAdapters, 比如例子中logger和hbase
- 目前client adapter數據訂閲的方式支持兩種,直連canal server 或者 訂閲kafka/RocketMQ的消息
(2) conf/es7目錄下新增映射配置文件
adapter將會自動加載
conf/es7
下的所有.yml
結尾的配置文件
新增表映射的配置文件,如 sys_user.yml
內容如下:
dataSourceKey: defaultDS
destination: example
groupId: g1
esMapping:
_index: sys_user
_id: id
upsert: true
sql: "select id, username,
, case when sex = 0 then '男' else '女' end sex
, case when is_del = 0 then '否' else '是' end isdel
from sys_user"
etlCondition: "where update_time>={}"
commitBatch: 3000
- dataSourceKey 配置
application.yml
裏srcDataSources
的值 - destination 配置
canal.deployer
的Instance
名 - groupId 配置
application.yml
裏canalAdapters.groups
的值 - _index 配置索引名
- _id 配置主鍵對應的字段
- upsert 是否更新
- sql 映射sql
- etlCondition etl 的條件參數,全量同步時可以使用
- commitBatch 提交批大小
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語句中
Elastic Search的mapping 屬性與sql的查詢值將一一對應(不支持 select *), 比如: select a.id as _id, a.name, a.email as _email from user, 其中name將映射到es mapping的name field, _email將 映射到mapping的_email field, 這裏以別名(如果有別名)作為最終的映射字段. 這裏的_id可以填寫到配置文件的 _id: _id映射
4.4.3. 啟停命令
啟動
bin/startup.sh
關閉
bin/stop.sh
4.5. 遺留問題
目前使用的 1.1.5-SNAPSHOT
版本由於還不是發佈版,發現 canal-adapter
的集羣部署有個bug,配置 zookeeper
地址後啟動會出現以下異常:
java.lang.LinkageError: loader constraint violation: when resolving method "com.alibaba.otter.canal.common.zookeeper.ZkClientx.create(Ljava/lang/String;Ljava/lang/Object;Lorg/apache/zookeeper/CreateMode;)Ljava/lang/String;" the class loader (instance of com/alibaba/otter/canal/connector/core/spi/URLClassExtensionLoader) of the current class, com/alibaba/otter/canal/client/impl/running/ClientRunningMonitor, and the class loader (instance of sun/misc/Launcher$AppClassLoader) for the method's defining class, org/I0Itec/zkclient/ZkClient, have different Class objects for the type org/apache/zookeeper/CreateMode used in the signature
at com.alibaba.otter.canal.client.impl.running.ClientRunningMonitor.initRunning(ClientRunningMonitor.java:122) [connector.tcp-1.1.5-SNAPSHOT-jar-with-dependencies.jar:na]
at com.alibaba.otter.canal.client.impl.running.ClientRunningMonitor.start(ClientRunningMonitor.java:93) [connector.tcp-1.1.5-SNAPSHOT-jar-with-dependencies.jar:na]
at com.alibaba.otter.canal.client.impl.SimpleCanalConnector.connect(SimpleCanalConnector.java:108) [connector.tcp-1.1.5-SNAPSHOT-jar-with-dependencies.jar:na]
at com.alibaba.otter.canal.client.impl.ClusterCanalConnector.connect(ClusterCanalConnector.java:64) [connector.tcp-1.1.5-SNAPSHOT-jar-with-dependencies.jar:na]
at com.alibaba.otter.canal.connector.tcp.consumer.CanalTCPConsumer.connect(CanalTCPConsumer.java:59) [connector.tcp-1.1.5-SNAPSHOT-jar-with-dependencies.jar:na]
有以下3個解決思路:
- adapter暫時使用單實例模式,等待官方解決問題。
- 自行修復bug
- 使用
MQ
模式(adapter則無需註冊到zookeeper了)
該 BUG 已修復:https://github.com/zlt2000/canal
五、監控
canal
默認已通過 11112
端口暴露同步相關的 metrics
信息,只需通過集成 prometheus
與 grafana
即可實現實時監控同步情況,效果圖如下:
指標 | 簡述 |
---|---|
Basic | Canal instance 基本信息。 |
Network bandwith | 網絡帶寬。包含inbound(canal server讀取binlog的網絡帶寬)和outbound(canal server返回給canal client的網絡帶寬)。 |
Delay | Canal server與master延時;store 的put, get, ack操作對應的延時。 |
Blocking | sink線程blocking佔比;dump線程blocking佔比(僅parallel mode)。 |
TPS(events) | Canal instance消費所有binlog事件的TPS, 以MySQL binlog events為單位計算。 |
TPS(transaction) | Canal instance 處理binlog的TPS,以MySQL transaction為單位計算。 |
TPS(tableRows) | 分別對應store的put, get, ack操作針對數據表變更行的TPS。 |
Client requests | Canal client請求server的請求數統計,結果按請求類型分類(比如get/ack/sub/rollback等)。 |
Client QPS | client發送請求的QPS,按GET與CLIENTACK分類統計。 |
Empty packets | Canal client請求server返回空結果的統計。 |
Response time | Canal client請求server的響應時間統計。 |
Store remain events | Canal instance ringbuffer中堆積的events數量。 |
Store remain mem | Canal instance ringbuffer中堆積的events內存使用量。 |
六、總結
- 準備MySQL
- 開啟binlog(row模式)
- 準備同步權限的用户
- 創建canal-admin的庫表
- 準備zookeeper
- 部署canal-admin
- 創建集羣
- 創建server:關聯集羣
- 創建Instance:關聯集羣,並配置源庫信息
- 啟動canal-deployer
- 關聯canal-admin
- 啟動canal-adapter
- 關聯zookeeper
- 配置源庫信息
- 關聯Instance
- 配置目標庫信息(es)
- 新增映射配置文件
掃碼關注有驚喜!
- 如何基於Security框架兼容多套用户密碼加密方式
- 基於Kubernetes(k8s)部署Dubbo Nacos服務
- 基於jib-maven-plugin快速構建微服務docker鏡像
- 基於minikube快速搭建單節點環境
- 隱私計算FATE-多分類神經網絡算法測試
- 隱私計算FATE-離線預測
- 隱私計算FATE-模型訓練
- 隱私計算FATE-核心概念與單機部署
- Hyperledger Fabric 核心概念
- Hyperledger Fabric 2.x Java區塊鏈應用
- Hyperledger Fabric 2.x 自定義智能合約
- Hyperledger Fabric 2.x 環境搭建
- Spring Boot 如何熱加載jar實現動態插件?
- 如何基於Security實現OIDC單點登錄?
- 第三方API對接如何設計接口認證?
- 免費正版 IntelliJ IDEA license 詳細指南
- ClickHouse性能優化?試試物化視圖
- 全量同步Elasticsearch方案之Canal
- Canal高可用架構部署
- 大數據量查詢容易OOM?試試MySQL流式查詢