DTM是一款开源的GO语言分布式事务管理器,解决跨数据库、跨服务、跨语言栈更新数据的一致性问题。
DTM可适合多语言栈的公司使用。方便go、python、php、nodejs、ruby、c# 各类语言使用。
支持的分布式事务协议包括:SAGA,TCC,XA和二阶段消息这几种模式。
官方网站:https://dtm.pub/
1.启动DTM服务#
项目
1 | https://github.com/dtm-labs/dtm |
git dtm项目
1 | git clone https://github.com/dtm-labs/dtm && cd dtm |
启动dtm
1 | ./dtm |
dtm运行后,会监听两个端口
1 | http:36789 |
2.分布式事务协议#
1.SAGA模式#
Saga核心思想是将长事务拆分为多个短事务,由Saga事务协调器协调,如果每个短事务都成功提交完成,那么全局事务就正常完成,如果某个步骤失败,则根据相反顺序一次调用补偿操作。
适用场景:适合需要最终一致性的大型跨服务事务,且允许一定时间的临时不一致。
优点:实现简单,不需要锁定资源,性能高。
缺点:数据一致性较弱,可能存在短时间的不一致。
参考:https://dtm.pub/practice/saga.html
2.TCC模式#
TCC分为3个阶段
- Try 资源预留阶段:尝试执行,完成所有业务检查(一致性), 预留必须业务资源(准隔离性)
- Confirm 确认阶段:如果所有分支的Try都成功了,则走到Confirm阶段。Confirm真正执行业务,不作任何业务检查,只使用 Try 阶段预留的业务资源
- Cancel 取消阶段:如果所有分支的Try有一个失败了,则走到Cancel阶段。Cancel释放 Try 阶段预留的业务资源。
适用场景:适合强一致性要求的场景,例如支付扣款、库存预扣等需要确保每个操作的资源在短时间内完全一致。
优点:可以精细控制资源的锁定和释放,提高一致性。
缺点:实现复杂,需为每个操作编写补偿逻辑。
参考:https://dtm.pub/practice/tcc.html
3.二阶段消息模式#
DTM的二阶段消息模式不依赖消息队列,只依赖背后的存储 MySQL/Redis。
参考:https://dtm.pub/practice/msg.html
1.两阶段提交(2PC)的基本原理#
**DTM的二阶段消息 **是 两阶段提交(2PC,Two-Phase Commit)的一种实现方式。
两阶段提交是经典的分布式事务协议,主要分为两个阶段:
- 第一阶段(准备阶段):协调者向参与者发送 “准备提交” 请求,参与者根据自己的操作(如数据库操作)决定是否可以提交事务。如果所有参与者都同意提交,协调者进入第二阶段。
- 第二阶段(提交阶段):如果所有参与者都返回 “同意” 的响应,协调者会发送 “提交” 命令;如果有任何参与者返回 “不同意” 或者失败,协调者会发送 “回滚” 命令。
2.DTM的二阶段消息模式 vs 本地消息表#
本地消息表这个方案最初是 ebay 架构师 Dan Pritchett 在 2008 年发表给 ACM 的文章。设计核心是将需要分布式处理的任务通过消息的方式来异步确保执行。
如果采用本地消息表,需要的工作包括:
- 在本地事务中执行本地业务逻辑,将消息插入消息表并最后提交
- 编写轮询任务,将本地消息表的消息,发给消息队列
- 消费消息,并将消息发给相应的处理服务
两者对比,二阶段消息有以下优点:
- 无需学习或维护任何消息队列
- 不需要处理轮询任务
- 不需要消费消息
适用场景:适用于可异步执行的业务,且后续操作无需回滚的业务
3.DTM的二阶段消息模式 vs 基于RocketMQ的事务消息#
在本地消息表方案中,生产者需要额外创建消息表,还需要对本地消息表进行轮询,业务负担较重。阿里开源的RocketMQ 4.3之后的版本正式支持事务消息,该事务消息本质上是把本地消息表放到RocketMQ上,解决生产端的消息发送与本地事务执行的原子性问题。
事务消息特点如下:
- 长事务仅需要分拆成多个任务,并提供一个反查接口,使用简单
- 事务消息的回查没有好的方案,极端情况可能出现数据错误
两者对比,二阶段消息有以下优点:
- 无需学习或维护任何消息队列
- 本地事务与发送消息之间的复杂操作需要手动处理,一不小心可能出现bug。而二阶段消息则是全自动处理
- 不需要消费消息
适用场景:适用于可异步执行的业务,且后续操作无需回滚的业务
4.DTM的二阶段消息模式#
对比于前面讲述的队列方案,二阶段消息还有很多额外的优点:
- 二阶段消息整个暴露的接口,完全与队列无关,只跟实际的业务和服务调用相关,对开发人员更加友好
- 二阶段消息不用考虑消息队列消息堆积及其他故障等问题,因为二阶段消息只依赖DTM,开发人员可以认为DTM与系统中其他一个普通无状态服务一样,只依赖背后的存储 MySQL/Redis。
- 消息队列是异步的,而二阶段消息同时支持异步和同步,默认异步,只需要打开msg.WaitResult=true,那么可以同步等待下游服务完成
- 二阶段消息还支持同时指定多个下游服务
参考:https://dtm.pub/practice/msg.html
4.XA模式#
XA是由X/Open组织提出的分布式事务的规范,XA规范主要定义了**(全局)事务管理器(TM)和(局部)资源管理器(RM)**之间的接口。
XA 事务的执行方式采用 两阶段提交协议(2PC)。
XA 事务依赖数据库的 XA 接口(如 MySQL、PostgreSQL、Oracle 都支持 XA),本地的数据库如mysql在XA中扮演的是RM角色。DTM在XA中负责TM角色。
XA一共分为两阶段:
- 第一阶段(prepare):即所有的参与者RM准备执行事务并锁住需要的资源。参与者ready时,向TM报告已准备就绪。
- 第二阶段 (commit/rollback):当事务管理者(TM)确认所有参与者(RM)都ready后,向所有参与者发送commit命令。
参考:https://dtm.pub/practice/xa.html
5.总结#
- 二阶段消息模式:适合不需要回滚的场景
- saga模式:适合需要回滚的场景
- tcc事务模式:适合一致性要求较高的场景
- xa事务模式:适合并发要求不高,没有数据库行锁争抢的场景