Go程序无法运行Debezium,仅能作为下游消费者接入其输出的Kafka JSON变更事件;需用kafka-go消费,解析before/after/op/source字段,并基于db+table+ts_ms+op实现幂等写入。

Go 本身不直接支持 Debezium,Debezium 是 JVM 生态的 CDC 工具,Go 程序只能作为下游消费者接入其输出流,而非运行或嵌入 Debezium。
Debezium 输出的数据格式和协议决定了 Go 的接入方式
Debezium 默认将变更事件以 JSON 格式写入 Kafka(也可配成 Pulsar 或 SQS),每个消息的 value 是包含 before、after、op、source 等字段的结构化数据。Go 程序只需用标准 Kafka 客户端消费这些 topic,并反序列化 JSON 即可拿到变更记录。
- 必须确认 Debezium connector 配置了
key.converter和value.converter为org.apache.kafka.connect.json.JsonConverter,且schemas.enable=false(否则 Go 解析带 schema 的 JSON 会多一层嵌套) - 典型
op值为c(create)、u(update)、d(delete)、r(read,快照阶段) -
source字段里有db、table、ts_ms,是做路由和幂等的关键依据
用 github.com/segmentio/kafka-go 消费 Debezium topic 的关键点
这是目前 Go 社区最轻量、无 CGO 依赖的 Kafka 客户端,适合处理 Debezium 这类高吞吐低延迟的变更流。
- 连接时需设置
GroupID,避免重复消费;若多个 Go 实例共用一个 GroupID,Kafka 会自动做 partition 分配 - 必须手动解析
msg.Value:先json.Unmarshal到 map[string]interface{} 或自定义 struct,不要跳过after为 null(delete 场景)或before为 null(insert 场景)的判断 - 示例中常见错误是直接用
json.Number解数字字段导致 panic,建议统一用float64接收再转 int,或用json.RawMessage延迟解析
// 示例:解析一条 Debezium 变更
type DebeziumEvent struct {
Before json.RawMessage `json:"before"`
After json.RawMessage `json:"after"`
Op string `json:"op"`
Source struct {
DB string `json:"db"`
Table string `json:"table"`
TsMs int64 `json:"ts_ms"`
} `json:"source"`
}
var event DebeziumEvent
if err := json.Unmarshal(msg.Value, &event); err != nil {
// 记录日志并跳过,不要 panic
continue
}
如何保证至少一次语义和避免重复写入
Debezium + Kafka 默认提供 at-least-once 语义,Go 消费端必须自己实现幂等写入,不能依赖 Kafka 的 offset commit 时机来控制精确一次。
- 推荐以
source.db + source.table + source.ts_ms + op拼接唯一 key,写入前查目标库是否已存在该 key 的变更记录(尤其 update/delete) - offset 提交策略:建议在成功写入下游后调用
conn.CommitOffsets,而不是用自动提交(容易丢数据) - 避免长事务阻塞:写入 DB 的逻辑必须超时可控,失败时应记录 error 并跳过该 msg,否则整个 partition 会卡住
真正难的不是解析 JSON,而是处理 delete 事件的级联影响、DDL 变更导致的 schema 不兼容、以及长时间停机后 Kafka retention 清掉旧 offset 的断点续传问题——这些都得在 Go 侧补足,Debezium 不管。

















