V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
cinlen
V2EX  ›  程序员

请教后端们关于分布式事务的实践

  •  
  •   cinlen · 7 天前 · 2676 次点击

    大约有这几个问题:

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

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

    27 条回复    2025-02-19 16:19:20 +08:00
    MelodYi
        1
    MelodYi  
       7 天前
    非金融相关行业。
    目前团队里涉及到分布式且具有事务性的东西,大多是同步接口创建任务、任务异步执行、任务异常自动重入的流程搞的。基本也没用到消息。
    Akitora
        2
    Akitora  
       7 天前
    蹲一个
    onikage
        3
    onikage  
       6 天前 via iPhone
    两步提交,后来优化流程干掉了,感觉这个不是啥好设计
    IDAEngine
        4
    IDAEngine  
       6 天前
    绝大部分场景都用不上分布式事务的,还不如搞 mysql 集群
    immango
        5
    immango  
       6 天前 via Android
    分布式事物加大了复杂性吧,建议最终一致性
    luciankaltz
        6
    luciankaltz  
       6 天前
    > 如果你加入了一家新公司,当前业务需要引入分布式事务,你会选择哪种方案?

    先考虑能不能用最终一致性处理,多系统的异常能不能用回滚解决。实在不行再考虑实时分布式事务。
    如果一家公司之前没有相关积累和经验,贸然上所谓的“分布式事务”的方案,大概率后面要踩不少坑
    yidinghe
        7
    yidinghe  
       6 天前
    最烦的不是分布式事务的实现,而是万一事务出问题导致数据不一致要怎么处理,要不要手工改数据来兜底,烦。
    realpg
        8
    realpg  
       6 天前
    必须分布式事务 95%以上场景就是个伪命题,架构师/总体组/CTO 动动脑子设计好就可以完全不用
    linxu
        9
    linxu  
       6 天前
    不会是天天吧
    kxg3030
        10
    kxg3030  
       5 天前 via iPhone
    用 dtm 这是目前比较好的解决方案 我们公司三年前我主推在使用 没有出现任何问题
    xuanbg
        11
    xuanbg  
       5 天前
    坚决不搞分布式事务,因为这玩意没法搞
    harlen
        12
    harlen  
       5 天前
    用 DTM
    me1onsoda
        13
    me1onsoda  
       5 天前 via Android
    @realpg 你的意思不要分布式存储?只要是分布式数据库绕不开分布式事务吧
    SilenceLL
        14
    SilenceLL  
       5 天前
    我们之前用了 seata ,后面业务太重了,大部分业务都改成基于消息队列的最终一致性。但是有些业务也有问题,举个云闪付的例子,支付后可以抽奖,但是因为是异步处理,跳转到抽奖界面基本上都没法直接抽,必须等一会刷新再抽。
    v2exgo
        15
    v2exgo  
       5 天前
    @SilenceLL 正常,用分布式事务的话,要加入中间协调结点,如果是事务 SQL 可能回滚 还要写补偿的 SQL ,不知道 seata 能不能自己生成补偿的 SQL ,我早年看过 seata 相关的技术文章,说他们可以基于 DAO 层 自己补写回滚补偿的 SQL

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

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

    不过我用过云闪付,当时就是无法立即抽,我猜测就是消息队列没消费完
    v2exgo
        16
    v2exgo  
       5 天前
    @SilenceLL 直接用 RPC 然后做分布式事务 很麻烦,主要还是处理事务回滚补偿的代码,如果有基于 SQL 层面自动分析 编写回滚补偿的话,可以考虑接受
    v2exgo
        17
    v2exgo  
       5 天前
    @SilenceLL 看了一下 seata 有一个 AT 模式,可以自动回滚补偿,有相关的实践经验介绍一下么
    v2exgo
        18
    v2exgo  
       5 天前
    @me1onsoda 所有的分布式事务都可以基于消息补偿机制,另外分布式事务 伸缩性很差,上游流量多,下游要跟着一起扩容,上游出了问题 下游死一大片,服务可用性很差,而且没法伸缩
    v2exgo
        19
    v2exgo  
       5 天前   ❤️ 1
    真实的实践就是

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

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

    你如果强行要把 订单->支付扣减->库存扣减 变成一个分布式事务,那就非常麻烦,首先上下游的伸缩性就完全没有了,毕竟流量一来,就都得跟着扩容,其实对于用户来讲,支付完成后,是可以等待一会 看到库存占用成功与否的,甚至从业务上你可以 加一个 库存扣减失败后,订单状态 跟 扣款退款的业务流程
    onichandame
        20
    onichandame  
       5 天前   ❤️ 1
    搞分布式事务只有一种情况:刷 kpi 。真实事求是的做设计,根本不可能有分布式事务的适用场景。
    - 要求单个请求强一致性:单进程内用数据库事务实现
    - 不要求强一致性:用消息队列异步事件链实现最终一致性
    giantreaper0
        21
    giantreaper0  
       5 天前
    我司用的就是 seata 的 AT + TCC ,用他是因为这个项目最初就有而且是老前辈们手写出来的,已经屎山了。总结下来就是能不用就不用分布式事务,只要模块拆分的够好绝大部分情况是不需要的,少部分需要的用消息队列做
    giantreaper0
        22
    giantreaper0  
       4 天前
    - 简单介绍一下我对 AT 的理解,就是在这个模式下,你等于无数据库的原生事务去执行,也就是你的每一条 sql 都会立即落库,如果发生了回滚,seata 有一份修改前的镜像用来回滚。
    - 这时候你就会问那回滚的时候被别的业务修改了怎么办,seata 会根据主键有一个全局锁,如果多个分布式(加粗)事务同时修改同一行能正常阻塞等待,因此这里就是有坑,代码那么多总会有只开了本地事务没开分布式事务的情况,这时候 seata 就会回滚失败,然后人工处理
    - 同时我司某些表还存在近似于全表删除的业务,这种情况下有可能甚至把 seata-server 直接打挂
    guanhui07
        23
    guanhui07  
       4 天前
    TCC DTM 应该也是补偿机制吧
    v2exgo
        24
    v2exgo  
       3 天前
    @giantreaper0 #22 感谢,这是实践才能踩坑到的
    v2exgo
        25
    v2exgo  
       3 天前
    @giantreaper0 #22 另外 TCC 跟 AT 能混着用么,TCC 不是需要自己手写补偿代码么
    giantreaper0
        26
    giantreaper0  
       2 天前
    @v2exgo 可以的,我个人的理解 AT 就是 seata 帮你实现的通用型 TCC
    giantreaper0
        27
    giantreaper0  
       2 天前
    我司的 TCC 实践有
    1. 用 TCC 实现库存的增减、锁库
    2. 有一些用数据库实现的任务队列,然后有定时任务轮训查询去执行任务会有一些数据其实还在全局事务进行中,但由于没有本地事务会导致也能查出来,这时候就需要利用 TCC ,在二阶段提交的时候将 "global_tx_commited" 设置为 1 ,定时任务只查询 global_tx_commited = 1 的任务
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2734 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 05:52 · PVG 13:52 · LAX 21:52 · JFK 00:52
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.