订单刚刚更新,搜索索引却还停留在几分钟前;缓存、统计服务和业务库之间,也常常靠定时任务反复查询来“追数据”。
如果你也遇到过这些问题,可以看看 cdc-go:一个 Go 编写的轻量级 MySQL CDC(Change Data Capture)服务。它读取 MySQL 的 ROW 格式 binlog,把行级变更转换成统一的 JSON 事件,再发送到 stdout、Redis、Kafka、RabbitMQ、RocketMQ 或 Pulsar。
简单说,业务库负责产生变更,cdc-go 负责把变更搬出来,后续服务通过消息中间件各自处理。业务代码不必为了“数据变了”而不停扫表。
它是怎么工作的?
1 | MySQL ROW binlog |
cdc-go 以 MySQL replication client 的身份读取 binlog,识别每行记录的新增、更新和删除,再将事件投递到配置的输出端。它本身不负责替你更新 ES 或刷新缓存;它提供的是一条可供下游订阅的变更流。
输出的事件结构保持一致。下面是一次更新的示意:
1 | { |
row.type 为 insert、update 或 delete。新增事件的 data 是新增后的行,删除事件的 data 是被删除的行;更新事件则同时包含变更后的 data 和变更前的 old。因此,下游不需要为每一种消息队列重新设计一套数据格式。
为什么值得一试?
不用定时扫表
传统轮询往往意味着固定间隔、额外查询负载和“多久同步一次”的取舍。直接读取 binlog,可以按行变更获取事件,更适合把数据库变化及时传递给下游系统。
输出端选择多
开发时可以用 stdout 直接观察 JSON;接入现有基础设施时,可以选择 Redis、Kafka、RabbitMQ、RocketMQ 或 Pulsar。位点则可以保存在本地文件或 Redis 中。单机验证可以从文件存储开始;容器环境要确保位点存储具备持久性,并根据实际运行拓扑选择合适的方式。
过滤不需要的表
支持通过正则表达式排除系统库,或只订阅指定的数据库和表。把采集范围先收窄,能减少无关消息,也让后续消费者更容易管理。
配置适合部署环境
服务使用 YAML 配置,并支持在配置值中引用 ${VAR} 和 ${VAR:-fallback}。连接密码等环境相关参数不必写死在配置文件里;同一份配置也更容易在本机、容器和 Kubernetes 环境之间复用。
快速体验:MySQL 到 Kafka
先确认 MySQL 开启了 ROW 格式 binlog:
1 | [mysqld] |
CDC 连接账号需要有读取复制日志的权限;如果运行过程中需要查询表元数据,还需要相应的 SELECT 权限。生产环境建议创建专用账号,并为每个 replication client 使用唯一的 server_id,不要和 MySQL 副本或其他 CDC 服务冲突。
从源码构建:
1 | git clone https://github.com/chihqiang/cdc-go.git |
将 config.yml 复制为自己的配置文件,然后把需要的段落设为 MySQL、Redis 位点存储和 Kafka 输出,例如:
1 | store: |
这里的 server_id 要按环境选择一个未被其他 replication client 使用的值。启动时提供密码环境变量:
1 | SOURCE_MYSQL_PASSWORD='你的数据库密码' ./cdc-go -c config.local.yml |
第一次尝试也可以把 producer.type 设成 stdout,不接消息队列,先观察事件内容和表过滤结果。完整配置项、Docker 示例和 MySQL 权限说明可以查看项目的 README。
上线前,别忽略这几件事
位点恢复不等于端到端 exactly-once。 cdc-go 支持将 binlog 位点写入文件或 Redis,并在重启后从已保存的位置继续读取。但这不意味着业务消费者绝不会重复处理,或任意故障下都能自动完成端到端恢复。建议下游处理具备幂等性,并针对消息队列、位点存储和进程重启做故障演练。
位点存储要跟部署方式匹配。 如果用文件位点,容器重建后要确保保存目录仍然挂载在持久化卷上;否则本地文件随容器消失。多实例部署时也要明确位点的共享方式和运行拓扑,不要仅凭“支持 Redis”就直接启动多个读取者。
CDC 主要解决增量,不是全量迁移。 新服务首次上线时,通常还需要单独处理历史数据的全量初始化,并设计好初始化期间与增量事件的衔接。
消费者应当可重复执行。 重试和消息队列的投递语义可能让同一条变更被处理不止一次;更新缓存、写搜索索引或生成下游记录时,尽量使用业务主键和事件信息实现幂等。
另外,项目中的 cdc-go-task 是用于演示和参考的消费者,会读取消息并记录事件,并不是开箱即用的生产业务任务框架。接入实际业务时,应由自己的消费者实现数据校验、幂等、失败处理和监控。
适合什么场景?
如果你想把 MySQL 的增量变化分发给搜索索引、缓存刷新、异步业务处理或数据分析服务,又不希望每个服务都直接轮询数据库,cdc-go 值得作为一个轻量的候选方案。
它的价值不在于替代消息队列或完整的数据集成平台,而在于把“读取 MySQL 变更并输出统一事件”这件事做成一个配置清晰、容易试跑的独立服务。先用 stdout 看懂事件,再接入团队已有的消息中间件,往往是最省力的验证方式。