分布式环境下事务一致性

12 5月

在当今流行微服务体系结构中,一个看似简单的功能可能需要调用多个服务,并操作多个数据库。比如创建用户操作,首先需要在服务A创建用户的帐号,在服务B中创建对应的积分记录,然后服务C中添加用户优惠信息等,由于网络,服务自身的可用性等,这几个操作中的一个或者多个可能会失败,为了保持事物一致性,就必须有对应的手段或者技术。

实现分布式环境下的事务一致性保证有以下几种方式:

  1. 两阶段提交协议
  2. 三阶段提交协议
  3. TCC 协议
  4. 基于可靠消息投递方案
  5. 基于补偿模式方案

两阶段提交包括准备阶段和提交阶段,主要需要事务协调者TM和资源管理器RM参与。首先在准备阶段,首先 TM 发送指令到 RM,RM 对自身状态进行充分评估,如果 RM 经过评估认为操作能够完成, 那么锁定资源但是不提交。在提交阶段,如果每个RM都反馈成功准备的信息, 再进入第二步执行确认操作,即资源预留及操作均成功,TM发送RM提交操作的指令, RM如果没有成功,则需要执行逆操作来取消第一步操作的影响。

两阶段提交协议的主要问题在于虽然一致性很强,但是锁太重,如果TM出现故障,会出现阻塞。

三阶段提交协议从字面看就是对两阶段的补充,引入了超时机制,将准备阶段拆分为询问和预提交两个部分。询问时RM只响应是或者否,不锁定资源,超时就直接终止。预提交的时候RM再记录日志和执行锁。

很明显,三阶段虽然多了一个步骤,但是实际上只是提交发现无法执行的情况,之后并没有特别的改进。

TCC 协议会将一个任务拆分成三个环节:尝试(Try ) 、 确认(Confirm ) 、 取消(Cancel )。正常的流程是第一步先执行尝试操作,如果不成功,就执行逆操作取消第一步的影响。它和两阶段的区别在于RM需要具备一定的自动修复能力,如果RM中任何一个失败,就要求所有RM执行第一步的逆操作。Restful情况下的设计有一篇论文比较详细《Atomic Distributed Transactions: a RESTful Design》,公开下载的可以看看。

基于可靠消息投递方案相对比较简单,对于可以异步处理的事务,采用消息队列来处理,只要保证了幂等性(确保消息任意多次执行所产生的影响均与一次执行的影响相同)那么就可以重复重试即可。

基于补偿模式方案对应更业务一些。在目前所知的情况下,一旦有操作出现了不正常的情况,我们需要及时的去修复系统中有问题的子操作。这些操作最终的目的都是让系统的各个部分达到最终的一致性。

这里网上找到了可靠消息投递方案和TCC的示意图,可以参考一下:

参考链接:

https://segmentfault.com/q/1010000000304596

 

发表评论

电子邮件地址不会被公开。