MySQL 实时同步难题有救了!这款 Go 语言 CDC 工具,6 种下游输出 + 断点续传,开箱即用

2025-10-21 go mysql, bingo

做后端开发的同学,大概率都遇到过这样的场景:

业务需要将 MySQL 数据实时同步到 Kafka 做消息分发,或是同步到 Redis 做缓存更新,可传统方案要么依赖复杂的中间件,要么需要手写 binlog 解析代码,耗时又容易出 bug。

今天给大家安利一款轻量级 CDC 工具 ——dbxgo,基于 Go 语言开发,专门解决数据库变更实时同步问题,多数据源适配、断点续传、多下游输出这些核心能力全具备,关键是开箱即用,部署成本极低。

先说说:为什么需要一款 “轻量级 CDC 工具”?

在聊 dbxgo 之前,先搞清楚一个问题:我们为什么需要 CDC(变更数据捕获)工具?

日常开发中,“数据库变更同步” 是高频需求,比如:

  • 订单表数据变更后,实时同步到消息队列,触发后续的物流通知、财务对账;

  • 用户信息更新后,同步到 Redis 缓存,避免缓存与数据库不一致;

  • 业务数据实时同步到数据仓库,支撑实时报表分析。

但传统方案总有各种痛点:

  • 用 “定时查询数据库” 的方式,实时性差(分钟级延迟),还会给数据库带来额外压力;

  • 用 MySQL 自带的主从复制,只能同步到另一台 MySQL,无法对接 Kafka、Redis 等下游系统;

  • 用商业 CDC 工具(如 Debezium),配置复杂,依赖 ZooKeeper 等组件,中小项目用着 “杀鸡用牛刀”。

而 dbxgo 刚好补上了这个缺口:轻量级架构,不依赖多余组件,同时支持多下游输出,还能保证实时性和可靠性。

dbxgo 核心能力:3 个亮点解决同步痛点

作为一款专注于 “实用” 的 CDC 工具,dbxgo 的核心能力完全围绕开发者的实际需求设计,总结下来有 3 个亮点:

  1. 实时性拉满:直接解析 binlog,变更秒级捕获 + 标准 JSON 输出​

dbxgo 不搞 “定时轮询” 那套,而是直接解析 MySQL 的 binlog 日志 —— 数据库一旦发生增删改操作,binlog 会实时记录,dbxgo 能瞬间捕获这些变更,并输出结构统一的 JSON 事件,下游系统无需适配不同格式,拿到就能用。

下面是三种核心操作的真实 JSON 输出示例,与 dbxgo 实际运行结果完全一致:

(1)插入操作(insert)示例

插入操作会在 data 字段中完整保留新增数据,便于下游系统直接存储或处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"time": "2025-10-21T10:57:34.032902+08:00",
"server_id": 101,
"pos": 1085,
"row": {
"time": 1761015454,
"database": "dbxgo",
"table": "users",
"type": "insert",
"data": {
"create_time": "2024-10-17 14:30:00",
"id": 1001,
"name": "张三",
"phone": "13800138000"
}
}
}

(2)更新操作(update)示例

更新操作会同时包含data(新数据)和old(旧数据),这是 dbxgo 区别于简化同步工具的关键特性 —— 下游系统可通过对比两者差异,精准执行更新逻辑(比如只更新变化的 “phone” 字段),无需全量覆盖:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
"time": "2025-10-21T10:58:12.855275+08:00",
"server_id": 101,
"pos": 1437,
"row": {
"time": 1761015492,
"database": "dbxgo",
"table": "users",
"type": "update",
"data": {
"create_time": "2024-10-17 14:30:00",
"id": 1001,
"name": "张三",
"phone": "13800138001"
},
"old": {
"create_time": "2024-10-17 14:30:00",
"id": 1001,
"name": "张三",
"phone": "13800138000"
}
}
}

(3)删除操作(delete)示例

与常见认知不同,dbxgo 的删除操作会在 data 字段中保存被删除数据的完整信息,而非设为 null—— 这一设计能确保下游系统完整记录删除记录,便于后续数据回溯、备份或误删恢复:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"time": "2025-10-21T10:58:48.330295+08:00",
"server_id": 101,
"pos": 1750,
"row": {
"time": 1761015528,
"database": "dbxgo",
"table": "users",
"type": "delete",
"data": {
"create_time": "2024-10-17 14:30:00",
"id": 1001,
"name": "张三",
"phone": "13800138001"
}
}
}

从结构能看出,dbxgo 的事件包含三层关键信息,每一层都为实际业务场景设计:

  • 顶层EventData:time记录事件捕获时间,server_id对应 MySQL 实例 ID(多实例同步时便于区分),pos是 binlog 偏移量(用于断点续传);

  • 内层EventRowData:database和table明确变更归属,type标注操作类型,避免下游判断逻辑;

  • 数据层data/old:按操作类型精准保留数据,适配插入存储、更新对比、删除备份等不同需求。

  • 多端适配:1 个数据源,6 种下游输出任选​

dbxgo 目前已支持 MySQL 作为数据源(后续可能扩展更多数据库),而下游输出端的覆盖范围很广,主流的消息队列和存储系统基本都能对接,不用再手写适配代码:

  • 简单场景:输出到 stdout(控制台),方便开发调试时查看实时变更;

  • 缓存场景:同步到 Redis,支持自定义存储 Key(比如按 “dbxgo: 数据库名:表名” 格式命名,便于管理);

  • 消息队列场景:对接 Kafka、RabbitMQ、RocketMQ、Pulsar,无缝融入消息驱动架构,支撑高并发业务。

比如你想把 MySQL 的 “dbxgo.users” 表同步到 Kafka,只需在配置文件中指定 Kafka broker 地址和主题,启动后 dbxgo 会自动将上述标准 JSON 事件发送到指定主题,全程无需编写代码。

  1. 高可用不丢数据:断点续传 + 优雅关闭​

做数据同步,最怕的就是 “程序重启后,之前的同步进度丢了”,dbxgo 通过 “偏移量存储” 解决了这个问题:

它会把 binlog 的同步位置(对应 JSON 中的pos字段)保存在指定的存储介质里,支持两种方式,适配不同部署场景:

  • 文件存储:把偏移量保存在本地文件,适合单机部署(如小型项目的缓存同步),无需额外依赖;

  • Redis 存储:把偏移量保存在 Redis,适合分布式部署或多实例场景(如多 MySQL 实例同步到同一 Kafka 集群),确保多实例进度一致。

哪怕程序意外重启(如服务器断电、进程崩溃),dbxgo 也能从上次保存的pos位置继续同步,既不会重复处理已同步的事件,也不会遗漏重启期间的新变更。另外,它还支持 “优雅关闭”—— 收到停止信号(如执行kill命令)后,会先处理完当前正在解析的 binlog 事件,再清理连接、保存最新偏移量,避免数据在中途中断。

上手教程:3 步启动 MySQL 实时同步

dbxgo 的使用门槛很低,不管是本地运行还是 Docker 部署,都能快速搞定,这里以 “MySQL(dbxgo 数据库 users 表)→Redis” 为例,整理一套实战步骤,其他下游目标(如 Kafka、RabbitMQ)配置逻辑类似。

前置条件(必看)

在启动前,需要先完成两项准备工作,确保 binlog 能正常解析:

  1. MySQL 已开启 binlog,且配置满足要求(编辑 MySQL 配置文件 my.cnf 或 my.ini,添加以下 3 行,重启 MySQL 生效):
1
2
3
log-bin=ON  # 开启 binlog
server-id=101 # 每个 MySQL 实例的 ID 唯一,需与 JSON 中的 server_id 对应
binlog_format=ROW # 必须是 ROW 格式,才能捕获完整的 data/old 数据(STATEMENT 格式无法获取字段级变更)
  1. 准备一个有 “binlog 读取权限” 的 MySQL 用户,执行以下 SQL 授予权限(替换用户名和密码为实际信息):
1
2
3
4
5
6
7
8
9
10
11
-- Create an account
CREATE USER 'dbxgo'@'%' IDENTIFIED BY 'strong_password';

-- Authorization (the REPLICATION permission is required to read the binlog)
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'dbxgo'@'%';

-- If dbxgo needs to do metadata queries, it also needs read permissions
GRANT SELECT ON *.* TO 'dbxgo'@'%';

-- Refresh permissions
FLUSH PRIVILEGES;

步骤 1:安装 dbxgo

有两种安装方式,可根据是否有 Go 环境选择:

方式 1:源码构建(适合有 Go 环境的场景)

如果本地装了 Go 1.23 及以上版本(dbxgo 依赖的 Go 版本要求),可直接克隆代码构建:

1
2
3
4
# 克隆 GitHub 仓库代码
git clone https://github.com/chihqiang/dbxgo.git && cd dbxgo
# 构建可执行文件(生成 dbxgo 二进制文件)
go build -o dbxgo ./cmd/dbxgo/

步骤 2:写配置文件

dbxgo 用 YAML 格式的配置文件,核心就 3 部分:存储(偏移量)、数据源(MySQL)、输出(下游目标)。

这里给出 “MySQL(dbxgo.users 表)→Redis” 的完整配置示例(保存为 config.yml,关键参数已加注释):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 1. 偏移量存储配置(用 Redis 存储,适配后续可能的分布式部署)
store:
type: redis # 存储类型:file(文件)/redis(Redis)
redis:
addr: "127.0.0.1:6379" # Redis 地址(如果是集群,用逗号分隔多个节点)
password: "" # Redis 密码(没有密码就留空)
db: 0 # Redis 数据库编号(默认 0,建议用单独数据库区分偏移量数据)
key: "dbxgo:offset:mysql:101" # 存储偏移量的 Redis Key(包含 server_id,便于多实例区分)

# 2. 数据源配置(MySQL,对应 dbxgo 数据库的 users 表)
source:
mysql:
addr: "127.0.0.1:3306" # MySQL 地址
user: "dbxgo_user" # 有权限的 MySQL 用户(步骤 1 中创建的)
password: "dbxgo_password" # MySQL 密码
database: "dbxgo" # 要同步的数据库名(可选,指定后只同步该数据库)
include_tables: ["users"] # 要同步的表(支持正则,这里只同步 users 表)
exclude_tables: [] # 要排除的表(无则留空,如 ["users:history"] 排除历史表)
charset: "utf8mb4" # 数据库字符集,默认 utf8mb4,避免中文乱码

# 3. 下游输出配置(Redis,存储完整 JSON 事件)
output:
type: redis # 输出类型:stdout/redis/kafka/rabbitmq/rocketmq/pulsar
redis:
addr: "127.0.0.1:6379" # Redis 地址(与存储偏移量的 Redis 可相同或不同)
password: "" # Redis 密码
db: 1 # 用单独的 Redis 数据库存储事件(与偏移量数据库区分,便于管理)
key: "dbxgo:events:mysql:dbxgo:users" # 存储事件的 Redis Key(格式:工具名:用途:数据源:数据库:表,清晰易懂)
data_type: "list" # 存储类型:list(按顺序存储事件,下游用 LPOP 消费,推荐)/string(单条覆盖,不推荐)
max_len: 10000 # 可选,list 最大长度,避免数据过多占用内存(超过后自动删除旧数据)

步骤 3:启动同步

本地启动(二进制文件方式)

在 dbxgo 二进制文件所在目录,执行以下命令,指定配置文件启动:

1
./dbxgo -c config.yml

启动成功后,控制台会输出日志(如 “connected to MySQL”“started listening binlog”),此时操作 MySQL 的 dbxgo.users 表(插入、更新、删除数据),事件会自动同步到 Redis。

Docker 部署(适合生产环境或快速测试)

如果想避免本地环境依赖,可直接用 Docker 启动,通过环境变量传递配置(无需写 YAML 文件),示例命令如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
docker run -it --rm \
--name dbxgo-mysql-redis \
# MySQL 数据源配置
-e SOURCE_MYSQL_ADDR="127.0.0.1:3306" \
-e SOURCE_MYSQL_USER="dbxgo_user" \
-e SOURCE_MYSQL_PASSWORD="dbxgo_password" \
-e SOURCE_MYSQL_DATABASE="dbxgo" \
-e SOURCE_MYSQL_INCLUDE_TABLES="users" \
# 偏移量存储配置(Redis)
-e STORE_TYPE="redis" \
-e STORE_REDIS_ADDR="127.0.0.1:6379" \
-e STORE_REDIS_KEY="dbxgo:offset:mysql:101" \
# 下游输出配置(Redis)
-e OUTPUT_TYPE="redis" \
-e OUTPUT_REDIS_ADDR="127.0.0.1:6379" \
-e OUTPUT_REDIS_DB="1" \
-e OUTPUT_REDIS_KEY="dbxgo:events:mysql:dbxgo:users" \
-e OUTPUT_REDIS_DATA_TYPE="list" \
# dbxgo 镜像(替换为最新版本)
zhiqiangwang/dbxgo:latest

验证同步结果

启动后,可通过 Redis 命令查看同步的事件(以配置中的 Redis 为例):

1
2
3
4
5
6
7
8
# 进入 Redis 客户端
redis-cli
# 切换到存储事件的数据库(配置中是 db 1)
SELECT 1
# 查看事件总数(list 类型的长度)
LLEN dbxgo:events:mysql:dbxgo:users
# 查看最新的 1 条事件(输出结果与前文的标准 JSON 结构完全一致)
LRANGE dbxgo:events:mysql:dbxgo:users -1 -1

哪些场景适合用 dbxgo?

dbxgo 不是 “万能工具”,但在这些场景下,它能发挥最大价值:

  1. 中小项目的实时同步需求:不需要复杂的分布式架构,只想快速实现 “MySQL→下游系统” 的同步,dbxgo 比 Debezium 更轻量;
  2. 缓存实时更新:用户表、商品表变更后,需要立刻同步到 Redis,基于 JSON 中的data字段更新缓存,避免脏数据;
  3. 业务日志同步:订单日志、操作日志等数据,实时同步到 Kafka,下游消费端可通过type字段区分增删改操作,再写入 ES 做检索;
  4. 数据备份与回滚:删除操作会保留old字段,可基于该字段实现数据误删后的快速回滚;
  5. 本地调试 binlog:开发阶段想查看 MySQL 的 binlog 变更,不用直接解析 binlog 文件,dbxgo 输出到 stdout 就能看到完整的 JSON 事件结构。

如果你正在找一款 CDC 工具,可以参考这个判断标准:

  • 若需要对接多种数据库(如 PostgreSQL、MongoDB),且是大型分布式架构,可考虑 Debezium;
  • 若主要用 MySQL,需要轻量级、低部署成本,且依赖标准 JSON 结构(含server_id、pos、old等关键字段)做精细化处理,dbxgo 绝对是首选。

目前 dbxgo 还在持续迭代,后续可能会支持更多数据源(如 PostgreSQL)和输出目标,感兴趣的同学可以去 GitHub 查看types包的最新定义,或给作者点个 Star 关注更新~

GitHub 地址:https://github.com/chihqiang/dbxgo