概述

dtm 解决跨服务更新数据的一致性问题,提供了相关问题的一站式解决方案。

几乎每一个非单体的系统,几乎每一个订单系统,都会出现跨服务更新数据的需求,这样的需求是非常广泛的存在的,也是服务化/微服务化之后,带来的一个挑战。面对这样的情况,当前业内普遍认为分布式事务很难,问题很多,所以能不用就不用,因此多数情况下为了避免使用分布式事务框架,业务会自己做重试,定时检查数据一致性。

dtm 则彻底解决了分布式事务的各项难题,提供了一个非常易用的接口,整体方案大大优于业务自己手动解决,优于业务自己做重试,自己检查数据一致性等。dtm 就是要让大家回归到分布式事务本质,将应当由分布式事务框架解决的问题,交给分布式事务框架,改变“能不用就不用的”的现状,将“专业”的事情交给“专业”的组件去做。

dtm 将分布式事务的场景大致分为两类,一类不需要回滚,一类需要回滚。对于不需要回滚的场景,dtm 推荐使用二阶段消息,对于需要回滚的场景,dtm 推荐使用saga。

二阶段消息

对于不需要回滚的场景,当前业内大多使用本地消息表或事务消息,其中本地消息表,也称为发件箱模式。dtm 则在两者的基础上进行了创新,提出了二阶段消息,具备以下很多优点,而没有硬伤:

  • 将本地消息表或事务消息中,一两百行的代码,简化为五六行
  • 不用维护本地消息表中的轮询任务或订阅binlog
  • 自动处理事务消息中的回查,解决了 RocketMQ 回查在极端情况下回出现的数据不一致问题(已申请了专利)
  • 提供面向 API 的接口,用户只需要关心 API 调用,而不需要关心任何消息队列
  • 提供半同步的选项,允许调用者等待最终事务完成再返回用户,改善用户体验

二阶段提供的主要函数为 DoAndSubmit ,它让用户指定自己的业务处理逻辑,然后保证业务处理逻辑和后续的API调用的“原子性”(最终都完成)

SAGA

对于需要回滚的场景,当前业内知名的项目 Seata 推荐 AT 模式,而 dtm 推荐 SAGA 模式。 个人认为 Seata 主推的 AT 模式目前暂未获得大量的应用,其主要原因如下:

  • 原理复杂:AT 模式虽然提供了注解的这种简洁的使用方式,但是的原理非常复杂,涉及全局事务锁、镜像前数据、写数据锁等,上手难度很高。
  • 并发低:AT 与 XA 都会在事务进行过程中,锁住修改的数据,限制了并发,在订单系统扣减同一个库存商品的场景下,通常每秒只能够一二十单,因此这种方案不适合高并发场景。
  • 易出问题:AT 要求对分布式事务中修改的数据,如果其他服务进行了修改,必须加GlobalLock,否则会有脏写无法回滚的问题,而这样的约束是一个大一些的团队协作中,很难保证
  • 不支持全部SQL:AT 并不支持所有的SQL,官方文档里面有详细的说明

而 dtm 的 SAGA 模式原理以及使用都非常简单,用户只需要写好业务的正向操作和补偿操作,然后将所有的事务分支 URL 提交给 dtm 就可以了,剩下的事情全部由 dtm 去完成。 dtm 还有以下的优点:

  • dtm 还首创了子事务屏障技术,通过一个简单的函数调用,就可以解决掉幂等,空补偿,悬挂这样的乱序问题,极大的降低了业务编写人员的负担
  • dtm 的子事务屏障还支持了Redis,也很容易扩展到 mongo ,可以将各种多数据源组合为一个全局事务
  • dtm 支持多语言,可以将多个语言的微服务组合成一个全局事务,使用场景很广

其他模式

dtm 也支持了其他模式,使用的场景如下:

  • TCC: 如果业务对一致性要求高,不能接受 SAGA 模式中先修改再补偿的做法,那么可以考虑 TCC 模式,该模式可以由业务方自定义可见性,只有确定事务一定能成功,再修改数据
  • XA: 如果业务对并发的要求不高,不会出现热点数据争抢,那么可以使用 XA 模式

典型应用场景

dtm 可以在一下场景中,优雅的解决相关的问题

秒杀系统

现有的秒杀架构,为了支持高并发,通常把库存放在Redis中,收到订单请求时,在Redis中进行库存扣减。这种的设计,导致创建订单和库存扣减不是原子操作,如果两个操作中间,遇到进程crash等问题,就会导致数据不一致。

dtm 提出了一种全新的秒杀架构,完全解决了秒杀架构中的核心痛点。该架构能够支持每秒超万单精准扣库存,并且保证创建订单和扣减库存的数据最终严格一致。详情参见 秒杀系统

订单系统

绝大多数的订单系统都已经服务化,会将订单系统拆分为订单服务、库存服务、优惠券服务、支付服务、账户服务等等。通常一个下单操作会涉及:创建订单、扣减库存、扣减优惠券、创建支付单等等,如果这中间发生进程crash,那么会导致几个服务间数据不一致的问题,非常头疼。

dtm 建议采用上述的saga方式,来解决订单问题,可以保证数据的最终严格一致。用户只需要写好了相关服务的正向操作和补偿操作即可,就不需要担心数据一致性问题了。

详细的讲解和例子,可以参考 订单系统

缓存一致性

缓存是现在系统中必备的基础设施,用来缓解数据库的压力。但是一旦引入了缓存,那么数据就在两个地方进行了存储,那么如何才能够保证两者的一致性呢?业界已经有很多方案,典型的会依赖消息队列或者订阅数据库的binlog,这些方案都比较重,需要维护消息队列或canel,是个不小的负担。

dtm 致力于解决一致性问题,因此也提出了基于dtm的更加轻量级的方案,详情可以参考 缓存一致性

小结

dtm 在易用性上面做得非常优秀,如果你还在自己做重试,或者做手动补偿,那么请参考并试用 dtm ,你会发现 dtm 会给你带来简单优雅的架构方案,大幅提升你在这方面的开发效率,降低维护成本,彻底改观你对分布式事务“能不用就不用”的印象。