分布式事务解决方案ServiceComb - Omega源码阅读与分享
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分布式事务解决方案ServiceComb - Omega源码阅读与分享相关的知识,希望对你有一定的参考价值。
参考技术A
ServiceComb已经是Apache的顶级项目,包含两个组件,即 alpha 和 omega。
源码地址:https://github.com/apache/servicecomb-pack
alpha 是事务协调中心,保存事务日志,通过日志协调各个分支
demo 里面项目的各框架的例子:spring和dubbo saga tcc
docs 设计文档,最先应该熟悉的。
omega 负责与alpha通讯,子事务逻辑
pack-contracts gRPC通讯接口定义文件,通过中间文件生成客户端与服务端面代码,让开发者不必关心通讯过程
web 用angular写的web界面,可以查看事务的状态。
我们主要关注的alpha和omega的代码,gRPC知识是通讯基础非常重要,最好先了解gRPC和probuf、Kyro序列化对阅读源码
还是很有帮助的。但通讯部分只是简单带过。
GlobalTxId全局事务ID标记子事务是否同属性一个事务中
ParentTxId 父类的事务ID
localTxId子事务Id
Omega会面向切面编程的方式,向程序中注入相应的逻辑,初始化事务上下文OmegaContext,在事务处理的过程中向alpha报告事务状态,
实现saga协调协议和TCC协调协议,下面就是omega客户端要配置了三个信息
omega.enable=true或@EnableOmega的作用只标记开启Omega,Omega在SpringBoot上初始化过程:
OmegaSpringAutoConfiguration 通过@Configuration,在Spring框架启动时加载并配置
OmegaSpringConfig
作用:初始化各Bean,IdGenerator用来生成子事务Id Saga的事件Sender Tcc事件Sender回调CallbackContext
TransactionAspectConfig
对@SagaStart @Compensable注解AOP的切面编程对象初始
Omega内部机制:SagaStartAspect @SagaStart的AOP切面编程
TransactionAspect对@Compensable注解AOP切面编程
成功场景下,每个事务都会有开始和对应的结束事件。
TransactionAspect=>DefaultRecovery=>CompensableInterceptor
封装了通讯组件:dubbo fegin resttemplate servicecomb实现的通讯
这些组件各自通讯的基础上,在服务之间相互调用时,把globalTxId和localTxId传递过去,并注入Context中
如:omega-transport->omega-transport-resttemplate
RestTemplateConfig 配置拦截器TransactionClientHttpRequestInterceptor
TransactionClientHttpRequestInterceptor:把当前的上下文的globalTxId和localTxId放到请求里
TransactionHandlerInterceptor 服务提供者,把resttemplate传递过来的globalTxId和localTxId放到当前上下文里,
pack-contracts->pack-contract-grpc
gRPC的接口服务定义文件:GrpcCommon.proto GrpcTccEvent.protogrpcTxEvent.proto:这些文件在protobuf命令直接编译成java代码。
如何使用请看:proto文件gRpc基础
谢谢能看到最后的人:我分享我是怎么阅读源码的。源码阅读不能一上来就找到main入口一行一行的看。最先应该了解基本的组成架构、和用到了哪些技术栈,如果还用了你从来没见的技术,建议先去学习这门新的技术,再回头来看代码,熟悉了各模块相对应的功能后。我会找到一个切入口,猜一下它的实现方式,再根据猜测,带着疑问,去找答案。如果对整个项目的模块不是很清楚,最好先把源码里的Demo正常的运行。通过这样的简单学习,一步步的深入。有的代码的抽象是比较复杂的。可先跳过,当你对整个结构都非常了解了,这时再回头去读剩下的难点。最后有个总结有个对比就是最好结果。
分布式事务解决方案——柔性事务与服务模式
在分布式系统中,是无法使用本地事务保证数据的一致性的。一种标准的分布式事务就是全局事务(DTP模型)。他是基于2PC来控制的。但是由于2PC自身就存在同步阻塞的问题,这也就导致全局事务效率很低。所以,这种全局事务并不适合解决大型网站的分布式事务问题。
柔性事务
在业内,主要用来解决分布式事务的方案是使用柔性事务。所谓柔性事务,相比较与数据库事务中的ACID这种刚性事务来说,柔性事务保证的事“基本可用,最终一致。”这其实就是基于BASE理论,保证数据的最终一致性。
虽然柔性事务并不像刚性事务那样完全遵循ACID,但是,也是部分遵循ACID的,简单看一下关于ACID四个属性,柔性事务的支撑程度:
原子性:严格遵循
一致性:事务完成后的一致性严格遵循;事务中的一致性可适当放宽
隔离性:并行事务间不可影响;事务中间结果可见性允许安全放宽
持久性:严格遵循
柔性事务的基础
前面介绍过了柔性事务的定义,目前,在业内,关于柔性事务,最主要的有以下三种类型:异步确保型、补偿型、最大努力通知型。
这三种类型的柔性事务基本都有对应的实现,不同的场景需要使用不同的柔性事务类型。而这几种柔性事务类型,其实还是依赖一些基础模式的,或者叫做基础接口,基础功能。
比如,要想使用可靠消息最终一致来实现异步确保型柔性事务,就依赖接幂等操作和可查询操作。关于具体实现,我们在后面的文章中介绍,本文简单介绍下这些实现柔性事务依赖的基础模式。
注意,下面要介绍的柔性事务的模式,并不是柔性事务的方案。这些是做柔性事务的基础。也就是说,如果你想做柔性事务,你的接口和功能要满足下面的几个要求。不一定要都满足,因为不同的方案的要求不一样。但是都不满足的话,是不可能做柔性事务的。
可查询操作
可查询操作,几乎是所有的分布式解决方案都需要的。
举一个常见的分布式场景的例子,如订单处理这一功能
/ 支付订单处理 /
public void completeOrder() {
orderDao.update(); // 订单服务本地更新订单状态
accountService.update(); // 调用资金账户服务给资金帐户加款
pointService.update(); // 调用积分服务给积分帐户增加积分
accountingService.insert(); // 调用会计服务向会计系统写入会计原始凭证
merchantNotifyService.notify(); // 调用商户通知服务向商户发送支付结果通知
}
以上这个支付订单处理的例子中,除了订单服务本地更新订单状态以外的所有操作,都需要调用RPC接口来执行,这种情况单纯的本地事务就无法保证数据的一致性了。就需要引入分布式事务。在分布式事务执行过程中,如果某一个步骤执行出错,就需要明确的知道其他几个操作的处理情况,这就需要其他的服务都能够提供查询接口,保证可以通过查询来判断操作的处理情况。
为了保证操作的可查询,需要对于每一个服务的每一次调用都有一个全局唯一的标识,可以是业务单据号(如订单号)、也可以是系统分配的操作流水号(如支付记录流水号)。除此之外,操作的时间信息也要有完整的记录。
幂等操作
幂等性,其实是一个数学概念。幂等函数,或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数,如:
f(f(x)) = f(x)
在编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。也就是说,同一个方法,使用同样的参数,调用多次产生的业务结果与调用一次产生的业务结果相同。
这一个要求其实也比较好理解,因为要保证数据的最终一致性,很多解决防范都会有很多重试的操作,如果一个方法不保证幂等,那么将无法被重试。
幂等操作的实现方式有多种,如在系统中缓存所有的请求与处理结果、检测到重复操作后,直接返回上一次的处理结果等。
可补偿操作
提到事务,为了保证原子性,就可能发生commit和rollback,那么在分布式事务中,要想进行rollback,就需要提供可补偿操作。
比如上面的订单处理的例子中,在调用积分服务给积分帐户增加积分操作执行之后,经过分布式事务协调,最终决定回滚整个事务,那么就需要提供一个调用积分服务给积分帐户扣减积分的操作。
并且,补偿操作同时也需要满足幂等性。
TCC操作
TCC 即 Try-Confirm-Cancel。
Try: 尝试执行业务
完成所有业务检查(一致性) 预留必须业务资源(准隔离性)
Confirm:确认执行业务
真正执行业务 不作任何业务检查 只使用Try阶段预留的业务资源 Confirm操作要满足幂等性
Cancel: 取消执行业务
释放Try阶段预留的业务资源
Cancel操作要满足幂等性
这种类型和可补偿操作类似,就是提供一种提交和回滚的机制。是一种典型的两阶段类型的操作。这里说的两阶段类型操作并不是指2PC,他和2PC还是有区别的。
TCC与2PC协议比较 TCC位于业务服务层而非资源层 TCC没有单独的准备(Prepare)阶段,Try操作兼备资源操作与准备能力 ? Try操作可以灵活选择业务资源的锁定粒度(以业务定粒度) TCC有较高开发成本
总结
本文主要是简单介绍了一下柔性事务和柔性事务实现的基础。柔性事务是目前主流的分布式事务解决方案,其基础模式包含四个:幂等操作、可补偿操作、可查询操作和TCC操作。后续文章会分别介绍关于分布式事务的解决方案,敬请期待。
以上是关于分布式事务解决方案ServiceComb - Omega源码阅读与分享的主要内容,如果未能解决你的问题,请参考以下文章
中国优秀开源项目一等奖-Apache ServiceComb