Hmily 源码解析(二)—— Hmily事务工作流程「建议收藏」

Hmily 源码解析(二)—— Hmily事务工作流程「建议收藏」Hmily源码解析(二)前言这一篇不想谈论Hmily源码的技术实现,而是想在过了一遍hmily的实现后把hmily的工作思路单独地整理出来再进行一次总结。看看能不能进一步有所得。以hmily-demo-springcloud为例,它的实现思路如下。Hmily事务工作流程首先它是基于切面编程来实现分布式事务的操作,及通过日志记录TCC事务的信息以保证最终一致性。前…

大家好,又见面了,我是你们的朋友全栈君。


前言

  • 这一篇不想谈论Hmily源码的技术实现,而是想在过了一遍hmily的实现后把hmily的工作思路单独地整理出来再进行一次总结。看看能不能进一步有所得。

  • 以hmily-demo-springcloud为例,它的实现思路如下。


Hmily事务工作流程

  1. 首先它是基于切面编程来实现分布式事务的操作,及通过日志记录TCC事务的信息以保证最终一致性。
  2. 前端发起的一个请求,第一次进入一个@Hmily注解的函数的时候,就进入Hmily的事务管理了。
  3. 这时会进入切面方法,生成一个日志实例(HmilyTransaction实例)。日志实例里面存储了所有后续需要操作的信息,比如流转状态,执行函数信息等等,并在后续的操作中会根据需要加入新的信息。
  4. 日志实例 有一个执行状态,一开始时是PRE_TRY(开始执行try),并会通过一个并发队列异步存储到数据库中。顺便说一句,每个微服务都有一个日志表,存储着对应的日志。
  5. 关于异步存储要多说一句,hmily在设计的时候把许多操作,尤其是对日志表的删改查操作都改用异步操作的方式,这也是hmily如此高效的一个原因,值得重点分析。
  6. 刚才说到日志实例被异步存储到数据库的日志表中了,而另一边就开始执行我们的业务函数。
  7. 如果函数内部再调用的函数仍有@Hmily注解,这时候切面里面不做其他任何操作。
  8. 如果调用的函数有@Hmily注解且是RPC函数,也就是调用其他微服务的代理接口,这时候会把事务id(transId 是事务唯一的,一个分布式事务id只有一个,且被用于日志主键),及当前的角色状态一起作为请求头的参数。
  9. 被调用的微服务接收到请求后,如果执行到带有@Hmily的函数,会根据传递过来的transId 的事务信息生成又一个事务日志信息,状态为PRE_TRY(开始执行try),并异步存储到数据库中对应该微服务的日志表中。
  10. 接着继续执行该微服务的主体方法
  11. 如果该微服务又调用了其它微服务,则同第7步到第12步。
  12. 如果执行成功,修改 事务日志的流转状态为TRYING(TRY阶段完成),如果失败了则删除日志抛出异常。
  13. 现在回到第一个微服务,如果调用成功,会把该rpc接口信息存储到日志信息里面
  14. 如果还有调用其他微服务,则同第7步到13步。
  15. 如果所有的执行都没问题,这时候会把日志的状态改为TRYING(TRY阶段完成),然后发起异步任务执行confirm操作。
  16. confirm操作里会把状态改为CONFIRMING(“confirm阶段”),并异步存储到数据库中,然后通过反射存储在日志里面的confirmMethod方法,及调用rpc接口,将执行confirm的命令发送给对应的微服务。
  17. 其它微服务接收到confirm消息后,会根据该微服务的事务日志中存储的confirmMethod集合,一一执行,或再把该命令发送给被调用的下一层微服务,重复17步骤。
  18. 如果各个微服务在执行confirmMethod时,有失败的案例,会将失败的confirmMethod重新存储到对应的事务日志中,然后隔一定时间通过定时再次执行confirmMethod。直到一一成功或超过重试次数发出信息给维护人员处理。confirmMethod失败后的定时执行的这一步各个微服务已经是各自为政了,不用再自上而下的从第一个微服务发起任务。
  19. cancel方法同16步到18步。它的触发条件是,只要在try阶段里有哪个try出问题了,异常会层层抛出到最上层,后面的try都不执行。而前面执行过的try信息或调用过的rpc接口信息都会存储在事务日志中间。后面只要同confirm阶段一样,根据这些信息执行cancelMethod方法或对RPC接口发起cancel请求。

补充说明

  • RPC上面的Hmily注解的作用只是用于连接前后两个微服务的,使它们处于同一个分布式事务之下。

  • 各个微服务内部的@Hmily才是真正用于处理分布式事务的(执行try,confirm,canel,维护事务日志等)。
    在这里插入图片描述

  • 我觉得第12步有些问题。如果之前又调用了其它微服务,且也有事务,而且有事务是成功的,那在这边因为自己执行失败了一刀切的把日志信息删掉了。而被调用的微服务的事务再执行TRY后就无法再被执行了,因为中间断代了,无法接收到第一个发起者发下来的confirm命令或cancel命令,从而不知道该执行什么,最终导致数据不一致。

  • 我觉得在设计上,hmily要求分布式事务相关的业务代码要非常纯粹,如果中间有什么伴随着时间会有不同结果的操作(比如查询),可能就会由于查询结果不的不同导致破坏了最终一致性。

  • 之前有考虑过,同一个微服务内,会不会有两个@Hmily嵌套的情况。感觉有点傻,同一个微服务内部用hibernate事务管理就好了,不应该写成@Hmily嵌套,而且当前版本的@Hmily似乎也不支持这种做法,目前无法实现这种需求。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/143136.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • pycharm2022 02激活码【2022最新】

    (pycharm2022 02激活码)这是一篇idea技术相关文章,由全栈君为大家提供,主要知识点是关于2021JetBrains全家桶永久激活码的内容IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html4KDDGND3CI-eyJsa…

    2022年4月1日
    111
  • html 转换为cshtml,使用Html而不是csHtml

    html 转换为cshtml,使用Html而不是csHtml我想使用纯HTML页面而不是使用MVC.net的cshtml.但是当我通过右键单击索引添加视图时,我只能看到两个选项.publicclassHomeController:Controller{////GET:/Home/publicActionResultIndex(){returnView();}}Cshtml(剃刀)Aspx论坛但仍无济于事.我仍然没有看到添加ht…

    2022年6月23日
    49
  • Latex中单引号,双引号「建议收藏」

    Latex中单引号,双引号「建议收藏」写论文时候,需要写出英文的单引号和双引号单引号就是”这个符号双引号的话,如果输入两个英文输入下的””,比如”paper”,LaTeX编译显示的话就是两个向下的引号。正确应该是第一个向上方向的引号用“这个符号,就是输入两个下图的键盘上的符号,所以正确应该为:“paper”…

    2022年6月25日
    33
  • dpdk技术详解_dpdk acl

    dpdk技术详解_dpdk acligb_uio是dpdk内部实现的将网卡映射到用户态的内核模块,它是uio模块的一个实例。igb_uio是一种pci驱动,将网卡绑定到igb_uio隔离了网卡的内核驱动,同时igb_uio完成网卡中断内核态初始化并将中断信号映射到用户态。igb_uio与uio模块密切相关,我将从uio模块着手分析igb_uio模块的工作原理。uio模块分析uio可以看做是一种字符设备驱动,在此驱动中注册了单独的file_operations函数表,uio设备可以看做是

    2025年7月29日
    2
  • Cmd命令 查看端口被占用

    Cmd命令 查看端口被占用Cmd命令查看端口被占用1)第一步  打开cmd命令窗口,输入命令:netstat-ano|findstr输入端口号2)第二步  继续输入命令:tasklist|findstr第一步查询到的进程号3)第三步  根据第二步执行结果,打开任务管理器,将相应进程干掉即可…

    2022年5月19日
    138
  • Android学习笔记(四十):Preference的使用

    Android学习笔记(四十):Preference的使用

    2021年12月8日
    39

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号