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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 2022最新淘宝商品详情接口采集方法

    2022最新淘宝商品详情接口采集方法最新淘宝商品详情接口采集

    2022年7月21日
    11
  • fiddler进行弱网测试

    使用Fiddler对手机App应用进行抓包,可以对App接口进行测试,也可以了解App传输中流量使用及请求响应情况,从而测试数据传输过程中流量使用的是否合理。抓包过程:1、Fiddler设置1)启动Fiddler->Tools->FiddlerOptions2)HTTPS选项卡中,设置如下,勾选过程中如有弹窗允许即可;Connections选项卡中,勾选Allowre…

    2022年4月6日
    360
  • 搞定Prometheus普罗米修斯监控系统

    搞定Prometheus普罗米修斯监控系统学习目录能够安装prometheus服务器 能够通过安装node_exporter监控远程linux 能够通过安装mysqld_exporter监控远程mysql数据库 能够安装grafana 能够在grafana添加prometheus数据源 能够在grafana添加监控cpu负载的图形 能够在grafana图形显示mysql监控数据 能够通过grafana+onealert实现报警任务背景AAA公司是一家电商网站,由于公司的业务快速发展,公司要求对现有机器进行为业务监控,责成运维

    2022年7月19日
    60
  • MyBatis-延迟加载与MyBatis缓存(面试题)

    MyBatis-延迟加载与MyBatis缓存(面试题)MyBatis-延迟加载与MyBatis缓存-概念性MyBatis-延迟加载与MyBatis缓存MyBatis-延迟加载与MyBatis缓存-概念性延迟加载(面试题)1、什么是延迟加载(按需加载)2、延迟加载MyBatis缓存(面试题)1、Cache缓存2、MyBatis缓存分析3、一级缓存4、二级缓存原理开启二级缓存5、禁用二级缓存6、刷新二级缓存延迟加载(面试题)1、什么是延迟加载(按需…

    2022年5月21日
    33
  • 各种门平面图画法_cad门的画法_用CAD画门的平面图的方法步骤图

    各种门平面图画法_cad门的画法_用CAD画门的平面图的方法步骤图大家在CAD室内平面图中经常看到门吧,那么大家知道怎么用CAD画门的平面图呢?想了解的同学可以参照以下CAD画平面图的教程,自己尝试去画门的平面图!用CAD画平面图的门的方法1、如下图所显示,输入要画矩形的方框,输入rec。2、单击要如下图中点,在进行拉动。3、如果下图没有显示中点的话,可以右击对象捕捉,选择全部选择。4、如下图可以看得以画出一个小矩形框出来。5、可以看到了如下图用矩形画出的门框来…

    2022年5月25日
    64
  • springboottest 红_解决没有@RunWith 和 @SpringBootTest注解或失效问题[通俗易懂]

    springboottest 红_解决没有@RunWith 和 @SpringBootTest注解或失效问题[通俗易懂]导入别人的项目或者自己想创建一个测试类经常会遇见了这个问题没有@RunWith和@SpringBootTest注解或失效网上搜了搜全是我下面的第一个解决方案第二个才是重点解决方案1添加依赖如果你是springboot项目pom文件中添加org.springframework.bootspring-boot-starter-testtestMaven项目在项目上右键B…

    2022年5月25日
    251

发表回复

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

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