Kratos接入DTM的核心配置项有三个:dtmServer(必须为discovery协议地址,如discovery://localhost:2379/dtmservice)、busiServer(业务服务注册名,需与Kratos中app.Run传入的service name一致)、Driver(DTM conf.yml中须显式配置为'dtm-driver-kratos')。

Kratos 本身不提供分布式事务能力,它只管本地事务(比如单个数据库的 sql.Tx),跨服务的一致性必须靠外部事务协调器,DTM 是当前 Go 生态中最成熟、与 Kratos 集成最顺的方案。
kratos 接入 dtm 的核心配置项有哪些?
关键不是写多少代码,而是三个地址是否对得上:
-
dtmServer:DTM 协调器地址,必须是 discovery 协议(如discovery://localhost:2379/dtmservice),不能直接写grpc://...—— 否则 Kratos 客户端无法通过 etcd 自动发现 DTM 实例 -
busiServer:你的业务服务注册名,格式同上,例如discovery://localhost:2379/busi,要和你在 Kratos 服务中app.Run(...)里传入的 service name 一致 -
Driver:在 DTM 的conf.yml里必须显式配置Driver: 'dtm-driver-kratos',否则 DTM 不会加载 Kratos 适配器,dtmgrpc.NewMsgGrpc会静默失败
msg 模式 vs tcc 模式怎么选?
Msg 模式适合「最终一致性」场景,TCC 适合「强一致性」要求高的核心链路。两者在 Kratos 中调用差异明显:
- Msg 模式只需业务服务暴露普通 gRPC 方法(如
/api.trans.v1.Trans/TransOut),DTM 负责重试和幂等,但不保证实时回滚 —— 如果 TransOut 成功而 TransIn 一直失败,DTM 会持续重试,不会自动调补偿 - TCC 模式必须实现
Try/Confirm/Cancel三组方法,且每个方法都要注册到 DTM;Kratos 服务需用dtmgrpc.NewTccGrpc构造事务,Confirm和Cancel的超时时间必须显式设置(默认 0 会导致 DTM 认为不可调用) - 性能上,Msg 模式因无两阶段锁开销,吞吐更高;TCC 模式 Confirm 阶段失败率高时,Cancel 链路压力会陡增
为什么 dtm.NewMsgGrpc().Add() 后 Submit 总是 panic?
常见原因集中在协议和路径拼接上,不是代码逻辑问题:
- Protobuf service name 写错:
Add()第一个参数是完整 RPC 路径,必须严格匹配.proto文件里定义的package+service+rpc名,比如api.trans.v1.Trans/TransOut,少一个点或大小写错误都会导致 DTM 调用 404 - Kratos 服务未开启 gRPC 反射(
grpc.EnableReflection):DTM 在首次调用前会尝试反射获取服务元信息,关掉反射会导致Submit()报rpc error: code = Unimplemented - etcd 数据没清干净:重复运行示例后,旧的
/dtmservicekey 还在 etcd 里,但对应 DTM 进程已退出,Kratos 客户端拉取到无效 endpoint,表现为连接拒绝或 timeout
最易被忽略的是:DTM 的 gid 必须全局唯一且不能复用,Kratos 服务里别自己生成字符串,老老实实用 dtmgrpc.MustGenGid(dtmServer) —— 它内部依赖 etcd 的原子计数器,手动拼接容易撞库导致事务状态混乱。











