引言
昨日跟Java高级工程师陶鹏讨论之后,发现LCN框架的设计还是有一定的缺陷的,譬如“效率低”
、“入侵性高”
。毕竟是第三方公司的框架,还是有点不放心的,今天就来给大家讲解下“分布式事务控制”的框架原理设计。
在上一篇博客《分布式系列教程(21) -分布式事务解决方案(框架篇)》,我们知道了可以使用LCN框架来解决分布式事务,其基本事务控制原理图如下:
仿照LCN事务框架的设计流程,其实我们还是可以手动实现事务框架的。本文只描述思路,通过伪代码来实现。
分布式事务控制框架设计
为了方便理解,引出一个经典的场景:《订单系统调用库存系统案例》
在订单系统中,修改完「订单数据库」内容后,然后再远程调用「库存服务」来修改「库存数据库」内容。当然,这是没有异常的情况下是没有问题的,如果中途出现异常,那么在分布式系统中该如何处理呢?
下面来看看我的设计思路,整体分布式事务设计图如下::
流程图分析(与上图步骤序号无关):
- 「发起方」 和 「参与方」 都必须要注册到事务协调者中,建立一个长连接(技术:使用Netty或者MQ技术)。
- 「订单服务(发起方)」 调用 「库存服务接口(参与方)」 之前会向 「事务协调者」 请求创建一个事务分组ID(技术:使用注解+AOP技术+分布式锁)。
- 「订单服务」 使用HTTP(SpringCloud Feign底层使用HTTP)或者Netty(Dubbo协议底层使用Netty)远程调用 「库存服务接口」 的时候,在HTTP请求头会携带事务分组id给 「库存服务」。(技术:使用Feign或Dubbo)。
- 如果 「库存服务」 获取到对应请求头有事务分组id,那么执行库存服务的逻辑代码,否则不执行(技术:使用AOP技术)。
- 「库存服务」 执行完库存业务逻辑代码,会采用“假关闭”(假关闭就是重写JDBC的close,它不会提交事务的),发送逻辑操作成功给 「事务协调者」。(技术:使用JDBC重写+Netty或MQ)。
- 「事务协调者」 如果判断事务组的成员都“假关闭”完成了,通知所有参与者真正去提交事务(技术:使用Netty或MQ)。。
可能用到的技术
- 「注解」:主要用于修饰方法
- 「AOP」:主要处理事务(开始、提交、回滚)
- 「Netty或者MQ」:主要用作长连接减小宽带传输,但是耗内存
- 「分布式锁」:主要用于事务协调者生成事务分组id,保证唯一性(单机系统直接使用UUID、时间戳或者雪花算法,分布式系统使用Redis、DB或Zookeeper生成)。
- 「JDBC重写」:主要重写JDBC close方法(因为只有JDBC close掉才能真正的执行SQL实现持久化)。
- 「协议交互」:HTTP(推荐使用SpringCloud声明式服务Feign,底层使用的是HttpClient)或Netty(推荐使用Dubbo,Dubbo底层使用的是Netty)。
题外话
很多人在学习事务的时候,都会用到 开启事务begin()
、提交事务commit()
、回滚事务方法rollback()
,也许会提出疑问,为什么执行完插入或更新的SQL之后的代码报异常,调用rollback方法,这些SQL没有生效呢?其底层原理又是怎样的?下面来看看数据库等操作的流程图:
以上是本人对分布式事务解决框架的一些想法,也是个人的见解,有疑问的同学可以留下评论。实现起来是没这么简单的,如果时间允许的情况下,会手写分布式事务框架的例子给各位同学们看下(本文完)。