MySQL Binlog 增量同步工具go-mysql-transfer实现详解

一、 概述

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)、将生成的消息实时、批量发送给接收端

go-mysql-transfer原理

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支持下

五、使用文档

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343