大约有这几个问题:

当前使用/曾经使用的分布式事务的方案是什么?
你觉得比较好的方案是哪种?(综合考虑 “对架构复杂度提升”,”对代码可读性的影响“,“对程序员写代码的心智负担提升”等等)
综合下来,做这件事划算吗?是让你更轻松了,还是让你更累了?
如果你加入了一家新公司,当前业务需要引入分布式事务,你会选择哪种方案?

我看过网络上的理论文,但希望得到有真实实践过的后端同学们的分享,而不是全文背诵网络上的文章,这样就没有意义了。

非金融相关行业。
目前团队里涉及到分布式且具有事务性的东西,大多是同步接口创建任务、任务异步执行、任务异常自动重入的流程搞的。基本也没用到消息。

蹲一个

两步提交,后来优化流程干掉了,感觉这个不是啥好设计

绝大部分场景都用不上分布式事务的,还不如搞 mysql 集群

分布式事物加大了复杂性吧,建议最终一致性

如果你加入了一家新公司,当前业务需要引入分布式事务,你会选择哪种方案?

先考虑能不能用最终一致性处理,多系统的异常能不能用回滚解决。实在不行再考虑实时分布式事务。
如果一家公司之前没有相关积累和经验,贸然上所谓的“分布式事务”的方案,大概率后面要踩不少坑

最烦的不是分布式事务的实现,而是万一事务出问题导致数据不一致要怎么处理,要不要手工改数据来兜底,烦。

必须分布式事务 95%以上场景就是个伪命题,架构师/总体组/CTO 动动脑子设计好就可以完全不用

不会是天天吧

用 dtm 这是目前比较好的解决方案 我们公司三年前我主推在使用 没有出现任何问题

坚决不搞分布式事务,因为这玩意没法搞

用 DTM

你的意思不要分布式存储?只要是分布式数据库绕不开分布式事务吧

我们之前用了 seata ,后面业务太重了,大部分业务都改成基于消息队列的最终一致性。但是有些业务也有问题,举个云闪付的例子,支付后可以抽奖,但是因为是异步处理,跳转到抽奖界面基本上都没法直接抽,必须等一会刷新再抽。

正常,用分布式事务的话,要加入中间协调结点,如果是事务 SQL 可能回滚 还要写补偿的 SQL ,不知道 seata 能不能自己生成补偿的 SQL ,我早年看过 seata 相关的技术文章,说他们可以基于 DAO 层 自己补写回滚补偿的 SQL

最后 大部分都会采用消息队列达成最终一致性,如果代码有问题也可以修复后 进行补偿操作,

没法直接抽,可以让前端轮询一下,轮询成功前 按钮变灰色就行,服务端查询的压力稍微大点,这不是啥问题,查询压力 做集群扩缩容 比较容易

不过我用过云闪付,当时就是无法立即抽,我猜测就是消息队列没消费完

直接用 RPC 然后做分布式事务 很麻烦,主要还是处理事务回滚补偿的代码,如果有基于 SQL 层面自动分析 编写回滚补偿的话,可以考虑接受

看了一下 seata 有一个 AT 模式,可以自动回滚补偿,有相关的实践经验介绍一下么

所有的分布式事务都可以基于消息补偿机制,另外分布式事务 伸缩性很差,上游流量多,下游要跟着一起扩容,上游出了问题 下游死一大片,服务可用性很差,而且没法伸缩

真实的实践就是

80%的公司 搞微服务就压根没有这个概念,就是 RPC 调用,上下游不一致了,数据出问题了,程序员自己动手修数据,我待过的小公司都是如此,哪怕我在携程之前一个小 BU 也是靠手动修数据

剩下里面 80%的公司 会用消息队列去做,你可以用携程订一个酒店试试,他们就是先创建订单,然后支付,修改订单状态-为已支付,然后通过消息去扣库存,库存扣好了之后,会通知订单更改状态->已占用库存,APP 端 你支付完之后 是可以看到有一个轮询 订单状态的动作

你如果强行要把 订单->支付扣减->库存扣减 变成一个分布式事务,那就非常麻烦,首先上下游的伸缩性就完全没有了,毕竟流量一来,就都得跟着扩容,其实对于用户来讲,支付完成后,是可以等待一会 看到库存占用成功与否的,甚至从业务上你可以 加一个 库存扣减失败后,订单状态 跟 扣款退款的业务流程

搞分布式事务只有一种情况:刷 kpi 。真实事求是的做设计,根本不可能有分布式事务的适用场景。

  • 要求单个请求强一致性:单进程内用数据库事务实现
  • 不要求强一致性:用消息队列异步事件链实现最终一致性

    我司用的就是 seata 的 AT + TCC ,用他是因为这个项目最初就有而且是老前辈们手写出来的,已经屎山了。总结下来就是能不用就不用分布式事务,只要模块拆分的够好绝大部分情况是不需要的,少部分需要的用消息队列做

    • 简单介绍一下我对 AT 的理解,就是在这个模式下,你等于无数据库的原生事务去执行,也就是你的每一条 sql 都会立即落库,如果发生了回滚,seata 有一份修改前的镜像用来回滚。
  • 这时候你就会问那回滚的时候被别的业务修改了怎么办,seata 会根据主键有一个全局锁,如果多个分布式(加粗)事务同时修改同一行能正常阻塞等待,因此这里就是有坑,代码那么多总会有只开了本地事务没开分布式事务的情况,这时候 seata 就会回滚失败,然后人工处理
  • 同时我司某些表还存在近似于全表删除的业务,这种情况下有可能甚至把 seata-server 直接打挂