ACID,一个很熟悉的概念,实现ACID也并不困难,我们可以通过锁,时间序号等机制保证操作的顺序执行,让系统实现ACID特性,但是,在分布式系统中实现ACID,是有些困难的

ACID是一种对事务特性的抽象和总结,方便我们实现事务,如果实现了ACID,就实现了事务,再单机中,可以使用加锁,时间序列等操作,可以保证单个节点的ACID,但是节点之间的ACID并不好保证

如果才能保证分布式的事务呢?可以使用二阶段提交协议和TCC (Try-Confirm-Cancel)

假设还是利用苏秦的故事来进行讲解

假设秦国要攻击魏国,魏国和赵韩联合抗秦,而现在,必须保证三者必须同时出兵,同时行动,如果有一者不方便的时候,就立刻取消整个计划

图片

苏秦面对的这个新问题,典型的如何实现分布式事务的问题,这三个一起攻打秦国,这三个操作组成了一个分布式事务,要么全执行,要么全不执行

如果利用二阶段协议来提交一个操作,如何操作呢?

如果,苏秦将消息发送给赵国,赵接收到消息后就扮演协调者

然后交给赵来联系魏国和韩国进行发起二阶段提交

图片

然后发起了二阶段提交了,第一步的提交被称为投票阶段,为了方便演示,假设赵国和魏国,韩国都确认可以执行这个事务,同时,赵国,魏国,韩国都是锁定自己的资源,不会被他人再占用

图片

这样得到了所有人的确认yes,就可以进入提交执行阶段了,又名完成阶段,就是具体执行操作了

这样,赵国发起了具体执行操作,大致内容如下

图片

因为之前已经确定了都能执行,所以所有人都会执行这个事务,并在执行完成,将这些信息返回给赵国,赵国将整体事务的执行结果,返回给了苏秦,那么苏秦就解决了问题,协调好了作战方案

这就是二阶段提供协议,在这个协议中

可以将 赵明天攻打秦国,魏明天攻打秦国,韩明天攻打秦国,理解为分布式事务操作

将赵,魏,韩理解为分布式系统的三个节点,赵是协调者,苏秦就是客户端

将消息理解为网络消息

然后,将明天能否攻打秦国,设置为是否需要提交新的操作

在第一个阶段,每个参与者投票,一旦投票说明需要提交事务了,就不能放弃事务,就是说,在一个参与者投票提交事务之前,必须能够执行提交协议中自己的一部分,即时出现了故障或者中途被替换掉了

二阶段协议最开始是用来实现数据库的分布式事务的,不过最常用的是XA协议,MySQL就是利用了MySQL XA实现了分布式事务

但是存在着一些问题

比如在提交请求的阶段,需要预留资源,其他人不能操作

而且往往使用XA协议的系统都是些独立的,完整的系统,例如MySQL,是无法简单修改的

于是我们使用了TCC二阶段提交协议

Try预留 Confirm 确认 Cancel撤销,3个操作的简称,交由业务端去实现TCC协议

首先,我们先进入了预留阶段,大致步骤如下

图片

首先,直接由苏秦去发送消息,通知赵魏韩去预留相关的事件和资源,

三者都预留成功了,就是都是OK

在预留阶段的执行完成后,就是进入了确认阶段,大致的步骤如下

图片

首先,苏秦执行确认操作,通知,赵国,魏国,韩国明天攻打秦国

收到确认操作的相应,完成分布式的事务

如果预留阶段执行出错了,比如赵国发送了cancel的请求,收到了确认操作的响应,完成分布式的事务,如果预留阶段执行出现了错误,比如赵的一部分军队还在赶来的路上,无法出兵,就进入撤销阶段,大致步骤如下

图片

第一步骤,苏秦执行撤销操作,通知赵 魏 韩取消明天打秦国的计划

然后第二步,收到了撤销操作的响应

这样,在预留和确认两个阶段的协商之后,我们完成了这个分布式事务,赵 魏 韩 三国,要么一起进攻,要么按兵不动

TCC本质上就是补偿类型的事务,针对每一个操作都会有一个对应的确认操作和撤销操作,是一个业务层面的协议,其实就是需要放入到业务代码中实现的,为了实现这个一致性,确认和撤销的操作是具有幂等性的,因为这两个操作很可能会失败重试

而且TCC不会依赖于数据库的事务,而是在业务中实现了分布式业务,这样能够减轻数据库的压力,但对于业务代码的入侵性更加强,实现的复杂度更加高,所以在需要分布式事务的时候,优先考虑现成的事务型数据库,不能满足的时候,在考虑基于TCC的分布式事务

我们说了实现分布式系统ACID特性的方法,二阶段提交协议和TCC,我们明确几个重点,

1.二阶段提交协议,不仅仅是协议,也是一种经典的思想,二阶段提交在达成提交操作共识的算法中应用广泛,比如XA协议,TCC协议,Paxos,Raft等,这是一种常见的锤子思想

2.幂等性,对同一个操作的统一系统的任意多次执行,产生的影响和一次执行的影响相同.不会因为多次的执行产生副作用,常见的是Token,索引等,通过唯一标识,标记的方式消除多次执行的副作用

三阶段提交,虽然针对了二阶段提交的协调者故障, 参与者长时间锁定资源的痛点,引入了询问和超时机制,来减少资源被长期锁定的情况,不过这回导致集群各个节点在正常运行的情况下,使用更多的信息进行协商,增加系统的负载和响应延迟,所以三阶段提交协议很少被使用

而且,对于ACID特性,可以理解为CAP中一致性的边界,最强的一致性,也就是CAP的酸Acid,根据CAP理论,如果分布式系统,必须要求一致性,那么可用性必然受到影响,比如,如果一个节点的故障,导致整个分布式事务的执行都是失败的,绝大多数的场景对一致性的要求没怎么高,短暂的不一致是可以接受的,基于可用性和并发性能的考虑,所以一般可以考虑使用最终一致性

如果第一极端确认可以提交了,然后崩溃了怎么办,第二阶段没法真正的应用自己的那部分事务,看起来没法处理啊

这就是不同的阶段下的设计,在第二阶段提交的第一个阶段中的资源锁定中,如果没有回复,那么就不会发出提交指令,只有全部确认了才会发起,不然就就是回滚

如果确认了,那么第二阶段的提交,就只能成功,不能失败,那么就不会有的节点提交了,有的节点回滚了,如果有进程死亡,也会有新的进程补上去,不断重试

那么事务性分布式系统具有哪些优点,哪些缺点呢?

分布式事务追求的是,对于数据的极端一致性,对于这种系统,好处就是我们可以直接获取最新的数据,但是无法很好的保证分区容错性,和可用性,所以推荐一些系统信息数据进行使用

发表评论

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