dtmrs
Rust 写的分布式事务管理器,对标 DTM(Go,10.9k★)。 Apache-2.0,商用闭源接入没有障碍。
支持 SAGA / TCC / 二阶段消息 / XA / workflow 五种模式,存储可跑 sqlite / postgres / mysql,对外有 HTTP 和 gRPC 两套等价接口。
DTMRS_DB=sqlite:dtmrs.db
差异化:协调器可以嵌进你自己的进程
不需要单独部署服务,分支可以直接是进程内的函数 —— 没有网络、没有序列化:
use ;
let tc = builder
.handler
.handler
.start.await?;
tc.saga
.step
.step
.submit.await?;
Go 做不到这个形态:c-shared 会把整个运行时拖进宿主进程。所以 DTM 结构上必须独立部署。
通过 C ABI,Python / Node / JVM / C++ 也能这么嵌(见仓库的 bindings/)。
按你的角色选 feature
这个 crate 是门面 —— 加一个依赖就够,不用挨个加五个。但两端要的东西完全不同:
# 跑协调器(或把它嵌进自己进程)
= "0.2"
# 业务服务(RM):只需要屏障做幂等,
# 别把整个协调器(axum、tonic 那一堆)拖进去
= { = "0.2", = false, = ["barrier"] }
| Feature | 给你什么 |
|---|---|
server(默认) |
协调器本体、Embedded、dtmrs 二进制 |
grpc |
gRPC 服务端接口 + 调 grpc:// 分支 |
barrier |
子事务屏障 —— 任何业务服务接入都必需 |
xa |
业务侧(RM)的 XA 助手 |
full |
全都要 |
业务侧接入:屏障不是可选项
分支接口一定会被重复调用(TC 重试 + 崩溃恢复)。把屏障记录和业务 SQL 放进 同一个本地事务,一次解决幂等、空回滚、悬挂三个问题:
use ;
let mut tx = pool.begin.await?;
if bb.decide.await? == Execute
tx.commit.await?; // 原子性的来源
一条写错就会数据不一致的规矩
超时 ≠ 失败。 5xx、连接超时、gRPC 的 UNAVAILABLE / DEADLINE_EXCEEDED
都表示结果未知 —— 对方可能已经成功了,这时候回滚就是不一致。
只有 HTTP 409、gRPC ABORTED、或响应体里的 FAILURE 才触发补偿。
完整文档(中英双语 README、设计说明、四种语言绑定、各数据库实测的坑)见 github.com/jackwangfeng/dtmrs。
Apache-2.0。