• 分布式事物


    前提

    • 所有服务均有独立的事物管理机制,相互间没有任何关联.
    • 所有业务接口都有对应的补偿方法,用于将已经更新的数据还原到上一次的状态.
    • 本次实例为同步业务,理想状态下,只有全部成功或全部失败两种情况.

    正式开始

    正常流程

    一切安好.

    中途异常 - 补偿成功

    虽然发生了失败,但所有补偿都成功了.没有什么问题

    中途异常 - 补偿失败

    此时,主服务有三种处理方法

    1. 主服务无限重试补偿方法,直到补偿成功.
      这里有很麻烦的问题,如果下游的服务器已经停机,此时主服务的无限重试已经没有意义.在最坏的情况下,如果主服务访问量过大,而因为业务相同,主服务的线程池中的全部线程将全部处于阻塞状态,失去处理新请求的能力.
      同时,访问主服务的客户端有可能会放弃本次的连接,导致正在重试中的线程被回收,丢失所有状态
    2. 主服务尽可能调用补偿方法,并回滚自身事物,同时通知备用方案
      这里依靠备用方案对失败的补偿调用进行异步异步调用,已达到"最终一致"的效果.备用方案一般需要集成"可靠消息系统"
    3. 主服务直接放弃补偿与自身的回滚,并通知备用方案
      与2基本相同.在调用链比较长的情况下且补偿随机性失败,从上层看,2方案的调用结果(备用方案未执行时)将成锯齿状.而本方案,其对应
      的消费者直接以级联方式进行补偿的调用,最终完成全部补偿调用与主方法数据回滚,同样从上层看,方案3的调用结果(备用方案未执行时)将是平整的(只有失败处断裂).

    方案1直接pass
    方案2,3可以使用消息队列与对应的消费者进行实现.但是会有短暂的数据不一致问题

    中途异常(伪) - 触发补偿

    这种情况具体描述如下

    1. 正常远程调用
    2. 下游业务接收并进行处理
    3. 主服务认为网络超时(如等待数据库锁释放)或发生其他意外,从而触发补偿流程
    4. 下游业务完成请求处理
    5. 主服务发起并执行补偿流程(不包含4涉及的服务)

    解决方法

    1. 记录全局唯一识别码,当主服务发起补偿时,所有下游业务应该得知,并出发各自的补偿方法.
    2. 需要注意,在尝试解决过程中,如果主服务过早推送回滚通知,涉及独自提交的服务早于对应业务处理完成进行补偿,将会导致回滚通知失效.

    在这种情况下,上游业务回滚,下游业务独自完成了业务处理,造成数据问题. 会有短暂的数据不一致问题
    同样的,在这种情况下,调用补偿也有可能发生调用失败的情况.并且会更复杂,因为此时主服务会发出全局的回滚消息,需要处理补偿消息与回滚消息的顺序问题

    主服务断电 - 正常运行,补偿中,补偿失败中


    此时主服务状态全部丢失且下游业务状态错乱

    只能借用可靠消息对进行中的操作进行记录,并在再次开启后进行恢复

    总结

    • 在必须要使用RPC进行远程调用且事物复杂的情况下,应使用一个可靠的消息系统保证在各方断电,断网,回滚时能够即使恢复"状态".
    • 同时,应保证严格的幂等性,对于非幂等消息,根据实际情况,进行保留会消耗.
    • 所有经由消息系统的恢复性调用,均为异步操作,此时各方数据会出现不同步的问题.
    • 对于复杂性,即使是只有2步,也会产生意外,且补偿方法并不可靠.必须使用"可靠消息"系统进行保证(就是说,不要想要有"方便"这两个字).
    • 对于调用消息,进行两步验证,要做xxx与完成xxx,同时保证复苏用的业务数据即可.对于全局回滚消息,进行通用,同时保证复苏消息与回滚消息的幂等
    • 主服务自身的业务逻辑也应做成远程调用的模式,即有常规与补偿方法.而主方法本身不包含事物,以此进行统一管理
    • 基于上述的内容,已经很靠近TCC模式了,且需要扩展很多框架级代码与补偿代码.
  • 相关阅读:
    深入理解递归函数的调用过程
    关于字符串和字符数组的再讨论
    返回字符串的长度
    再写静态变量的有效范围
    一道关于返回指针和返回数组名的面试题
    关于TCP/IP的三次握手和四次挥手解释
    C++面向对象的编程(二)
    关于面试宝典中的检测并修改不适合的继承
    argc和argv
    基于C的文件操作(转)
  • 原文地址:https://www.cnblogs.com/heaven-elegy/p/11691410.html
Copyright © 2020-2023  润新知