一、 概述
go-mysql-transfer是一款MySQL數據庫實時增量同步工具。
能夠監聽MySQL二進制日志(Binlog)的變動,將變更內容形成指定格式的消息,實時發送到接收端。從而在數據庫和接收端之間形成一個高性能、低延遲的增量數據同步更新管道。
功能特性:
1、簡單,不依賴其它組件,一鍵部署
2、集成多種接收端,如:Redis、MongoDB、Elasticsearch、RocketMQ、Kafka、RabbitMQ、HTTP API等,無需編寫客戶端,開箱即用
3、內置豐富的數據解析、消息生成規則、模板語法
4、支持Lua腳本擴展,可處理復雜邏輯
5、集成Prometheus客戶端,支持監控告警
6、集成Web Admin監控頁面
7、支持高可用集群部署
8、數據同步失敗重試
9、支持全量數據初始化
二、 與同類工具比較
特色 | Canal | mysql_stream | go-mysql-transfer |
---|---|---|---|
開發語言 | Java | Python | Golang |
HA | 支持 | 支持 | 支持 |
接收端 | 編碼定制 | Kafka等 | Redis、MongoDB、Elasticsearch、 RabbitMQ、Kafka、RocketMQ、 后續支持更多 |
數據初始化 | 不支持 | 支持 | 支持 |
數據格式 | 編碼定制 | json(固定) | 規則(固定) Lua腳本 (定制) |
三、 設計實現
1、實現原理
1)、go-mysql-transfer將自己偽裝成MySQL的Slave,
2)、向Master發送dump協議獲取binlog,解析binlog并生成消息
3)、將生成的消息實時、批量發送給接收端
2、基于規則同步
使用配置可完成大部分同步工作,例如將表t_user同步到reids,配置如下規則:
rule:
-
schema: eseap #數據庫名稱
table: t_user #表名稱
column_underscore_to_camel: true #列名稱下劃線轉駝峰,默認為false
datetime_formatter: yyyy-MM-dd HH:mm:ss #datetime、timestamp類型格式化,不填寫默認yyyy-MM-dd HH:mm:ss
value_encoder: json #值編碼類型,支持json、kv-commas、v-commas
#value_formatter: '{{.ID}}|{{.USER_NAME}}|{{.REAL_NAME}}|{{if eq .STATUS 0}}停用{{else}}啟用{{end}}'
redis_structure: string # redis數據類型。 支持string、hash、list、set類型(與redis的數據類型一致)
redis_key_prefix: USER_ #key前綴
redis_key_column: USER_NAME #使用哪個列的值作為key,不填寫默認使用主鍵
t_user表,數據如下:
同步到Redis后,數據如下:
更多基于規則的同步案例 請見 https://www.kancloud.cn/wj596/go-mysql-transfer/2064425
3、基于Lua腳本同步
Lua作為專業的內置腳本語言,其設計目的是為了嵌入應用程序中,從而為應用程序提供靈活的擴展和定制功能。開發者只需要花費少量時間就能大致掌握Lua的語法,照虎畫貓寫出可用的腳本。
基于Lua的高擴展性,可以實現更為復雜的數據轉換,和處理工作
示例腳本:
local json = require("json") -- 加載json模塊
local ops = require("redisOps") -- 加載redis操作模塊
local row = ops.rawRow() --當前變動的一行數據,table類型,key為列名稱
local action = ops.rawAction() --當前數據庫的操作事件,包括:insert、updare、delete
local id = row["ID"] --獲取ID列的值
local userName = row["USER_NAME"] --獲取USER_NAME列的值
local key = "user_"..id -- 定義key
if action == "delete" -- 刪除事件
then
ops.DEL(key) -- 刪除KEY
else
local password = row["PASSWORD"] --獲取USER_NAME列的值
local createTime = row["CREATE_TIME"] --獲取CREATE_TIME列的值
local result= {} -- 定義結果
result["id"] = id
result["userName"] = userName
result["password"] = password
result["createTime"] = createTime
result["source"] = "binlog" -- 數據來源
local val = json.encode(result) -- 將result轉為json
ops.SET(key,val) -- 對應Redis的SET命令,第一個參數為key(string類型),第二個參數為value
end
t_user表,數據如下:
同步到Redis后,數據如下:
更多基于規則的同步案例 請見 https://www.kancloud.cn/wj596/go-mysql-transfer/2064425
4、監控告警
支持兩種監控模式,Prometheus和內置WebAdmin
Prometheus是流行開源監控報警系統和TSDB,其指標采集組件被稱作exporter。go-mysql-transfer本身就是一個exporter。向Prometheus提供應用狀態、接收端狀態、insert數量、update數量、delete數量、delay延時等指標。
5、高可用
支持基于zookeeper或者etcd構建高可用集群
只有leader節點響應binglog的dump事件,follower節點為蟄伏狀態,不發送dump命令,因此多個follower也不會加重MySQL數據庫的負擔
當leader節點出現故障,follower節點迅速替補上去,實現秒級故障切換
架構如下:
6、失敗重試
網絡抖動、接收方故障都會導致數據同步失敗,需要有重試機制,才能保證不漏掉數據,使得每一條數據都能送達。
當發生故障時記錄下故障時刻binglog的position(位移),等故障恢復后,從position處重新dump 數據,發送給接收端。確保不丟數據,并且保證數據順序性,正確性。
7、全量數據初始化
支持將數據庫中現存的數據一次性同步到接收端
你可以將數據庫原本就存在數據全量數據同步到接收端,然后再進行增量
也可以只使用全量數據同步功能,作為ETL工具使用
四、開源地址
項目開源地址:
gitee (速度更快) :go-mysql-transfer
github:go-mysql-transfer
如果此工具對你有幫助,請Star支持下