一、 概述
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支持下