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

·  阅读 1747

一、 概述

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
高可用 支持 支持 支持
接收端 编码定制 Kafka等(MQ) Redis、MongoDB、Elasticsearch、RabbitMQ、Kafka、RocketMQ、HTTP API
后续支持更多
全量数据初始化 不支持 支持 支持
数据格式 编码定制 Json(固定格式) 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后,数据如下:

更多基于规则的同步案例 请见 www.kancloud.cn/wj596/go-my…

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后,数据如下:

更多基于规则的同步案例 请见 www.kancloud.cn/wj596/go-my…

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工具使用

#四、开源地址

github:go-mysql-transfer

如果此工具对你有帮助,请在github中Star支持下

#五、使用文档

分类:
后端
标签:
收藏成功!
已添加到「」, 点击更改