easycar: 一个用go实现的分布式事务框架
图片拍摄于2022年7月23日,浙江杭州

对分布式业务一直感兴趣,之前一直被其他事情(懒)耽误了,最近终于动手了。

easycar是什么

easycar 是一个用go完结的支撑两阶段提交协议的分布式业务结构。现在还只支撑TCC,SAGA 形式,其他形式待开发。

在介绍easycar 之前,先简单介绍几个人物。

Transaction Coordinator(TC)

负责大局业务的办理,一切参加分布式业务的分支都会注册到coordinator,会给每个分布式业务分配一个仅有id,

当然还包含驱动大局 begin / commit /abort(我喜欢称rollback)。

Transaction Manager (TM)

有些时分也叫 Transaction Client,当然不同的完结也许都会换个名字,可是职责都大差不差。

一般经过TM对每个参加的RM建议一阶段的恳求,假设一阶段的RM悉数成功,那么TM会向TC建议commit恳求,否则建议rollback。

Resource Manager(RM)

用户维度的人物,办理本地业务处理的资源。其实你能够这么了解,假设你的订单服务部分接口参加了分布式业务,无论是第一阶段TM调用接口,仍是TC第二阶段调用接口,你的订单服务都会去负责本地的业务修正。

那么 easycar 上述人物有什么不同吗?

有的。既然TC负责的便是大局业务的办理,那么我把职责都给了它。即由TC向每个参加的RM建议一阶段的恳求,然后再根据一阶段的成果,建议二阶段的恳求。由TC接收整个分布式业务的生命周期。

是的,我弱化了上面TM的才干。在我眼里,TM本质上便是一个客户端。客户端只需求做一些数据封装,简洁化操作即可。所以即便没有客户端,其他语言的用户也能够直接经过http恳求easycar服务接口。

所以理论上,大部分形式下,不需求客户端也是能够直接运用easycar服务的。

支撑协议和业务形式同时混用

参加分布式业务的服务往往由不同的多个部分保护,或许部分新老项目交织,或许无法确保服务的协议是一致的。

另外,不同的服务所选用的业务形式详细是由:业务场景以及结构的成本来决议的。所以参加分布式业务之间所运用的业务形式不一定是统一的。

在这些基础上,easycar支撑协议混用(现在支撑http和原生的grpc服务),支撑部分业务形式混用(现在支撑TCC,Saga)。

支撑并发履行

假设现在有 order,account以及stock三个服务。

由这三个服务组成一个分布式业务。当用户下单时,需求经过这三个服务中内部一些接口(account 扣钱,stock减库存,order 创立订单)。

假设仅仅同步履行第一阶段,

那么第一阶段总履行时刻= (account+stock+order)。

很多场景下,分布式业务之间并不会存在履行依赖先后的关系。所以多个子业务一阶段能够同时并发履行。

流程就像这样:

easycar: 一个用go实现的分布式事务框架

上图咱们需求确保创立订单前必须先履行account扣减余额和stock扣减库存服务,才干创立订单order的服务。同时account和stock服务并不需求确保他们的履行顺序。

那么咱们一阶段总履行耗时能够大略=max(account,stock)+order。

因而,easycar是支撑分层并发履行的。对参加的RM经过设置的权重做分层,同一层的RM能够并发调用,一层处理完毕再接下一层。在这个基础上,当某个RM产生调用错误时,那么后边一层也不会履行了,整个分布式业务需求回滚。

异常处理

分布式业务中会出现一些问题,比方

  • 空补偿**:** Cancel恳求到来时,Try还没有履行,这时分这样的恳求咱们不能履行,理应直接返回。

  • 悬挂:Try履行时,Cancel已履行完结,不能履行,直接返回。

  • 幂等:一切操作的接口都存在这个问题。

这些问题需求用户自己去解决,结构不会主动帮你处理。

在我看来,这些问题自身便是服务的必要作业,而不是经过外部服务来帮你确保。

换句话说,前端说它参数做了校验,莫非后端就不校验接口了吗?

重试

这一块暂时还没决议终究方案。

我眼中的重试有两种形式:同步和异步。

同步的意思是说,当恳求RM服务产生错误的时分(网络、服务自身挂了、或许服务里的中间件挂了),经过固定次数固定时刻重试,这个时刻通常很短,比方一秒。

问题是服务挂的情况下,短时刻大概率好不了,重试简直或许是无用功。整个进程,客户端是堵塞等候的,白白耗费时刻。

异步重试选用指数退避算法之类的逻辑,比方第一次重试1分钟后,第2次2分钟…..,限制一个上限值,比方最多推迟一个小时仍是不行的话,那只能发告警,线下处理了。

这样的坏处是,

  • 首要用户不能实时获取本次分布式业务成果了(正在重试中),只能比及真实履行完毕的时分经过回调的方法异步告诉用户分布式业务终究成果。

  • 退避时刻越长,就意味着数据不一致的时刻越长。可是假设人工直接干预又存在极大的危险。比方在你人工干预的同时,正好逻辑已经开端履行了,或许会造成新的数据不一致。

状况流通图

easycar global 状况流通图

easycar: 一个用go实现的分布式事务框架

最后

easycar 开发不是很久,它还有很多作业需求去完结。感兴趣的能够一同参加。

项目地址:github.com/wuqinqiang/…