SpringCloud(四)微服务架构-事务⼀致性
分布式事务指事务的操作位于不同的节点上,需要保证事务的 AICD 特性。⽬前⽐较常⽤的分布式事务解决⽅案包括强⼀致性的两阶段提交协议、三阶段提交协议以及最终⼀致性的可靠事件模式、补偿模式、阿⾥的TCC模式。
事务是指由⼀组操作组成的⼀个⼯作单元,这个⼯作单元具有原⼦性(atomicity)、⼀致性(consistency)、隔离性(isolation)和持久性(durability)。
原⼦性:执⾏单元中的操作要么全部执⾏成功,要么全部失败。如果有⼀部分成功⼀部分失败那么成功的操作要全部回滚到执⾏前的状态。
⼀致性:执⾏⼀次事务会使⽤数据从⼀个正确的状态转换到另⼀个正确的状态,执⾏前后数据都是完整的。
隔离性:在该事务执⾏的过程中,任何数据的改变只存在于该事务之中,对外界没有影响,事务与事务之间是完全的隔离的。只有事务提交后其它事务才可以查询到最新的数据。持久性:事务完成后对数据的改变会永久性的存储起来,即使发⽣断电宕机数据依然在。
强⼀致性
两阶段提交协议
在分布式系统中,为了解决多个节点之间的协调问题,就需要引⼊⼀个协调者负责控制所有节点的操作结果,要么全部成功,要么全部失败。其中,XA协议是⼀个分布式事务协议,它有两个⾓⾊:事务管理者和资源管理者。我们可⽤把事务管理者理解为协调者,资源管理者理解为参与者。XA协议通过⼆阶段提交协议保证强⼀致性:
第⼀阶段准备:事务管理者向资源管理者发起准备指令,询问资源管理者预提交是否成功;资源管理者执⾏操作,并不提交,最后给出⾃⼰的响应结果
第⼆阶段提交:如果全部资源管理者都回复预提交成功,事务管理者则发起正式提交命令;如果其中⼀个资源管理者回复预提交失败,事务管理者则发起全部回滚命令
⼆阶段提交协议的缺点
同步阻塞问题:执⾏过程中,所有参与节点都是事务阻塞型的。当参与者占有公共资源时,其他第三⽅节点访问公共资源不得不处于阻塞状态。
单点故障:由于协调者的重要性,⼀旦协调者发⽣故障。参与者会⼀直阻塞下去。尤其在第⼆阶段,协调者发⽣故障,那么所有的参与者还都处于锁定事务资源的状态中,⽽⽆法继续完成事务操作。(如果
是协调者挂掉,可以重新选举⼀个协调者,但是⽆法解决因为协调者宕机导致的参与者处于阻塞状态的问题)
数据不⼀致:在⼆阶段提交的阶段⼆中,当协调者向参与者发送commit请求之后,发⽣了局部⽹络异常或者在发送commit请求过程中协调者发⽣了故障,这回导致只有⼀部分参与者接受到了commit请求。⽽在这部分参与者接到commit请求之后就会执⾏commit操作。但是其他部分未接到commit请求的机器则⽆法执⾏事务提交。于是整个分布式系统便出现了数据部⼀致性的现象。
三阶段提交协议
三阶段提交协议与⼆阶段的不同之处在于引⼊了超时机制来解决同步阻塞问题,此外加⼊预备阶段,尽可能最早发现⽆法执⾏的资源管理者并终⽌事务。
最终⼀致性
TCC模式
TCC模式将⼀个任务拆分为3个操作:Try、Confirm和Cancel。在TCC模式中,主业务服务负责发起流程,⽽从业务服务提供TCC模式的Try、Confirm和Cancel三个操作,还有⼀个事务管理器的⾓⾊负责控制事务的⼀致性。事实上,TCC模式也是⼀种⼆阶段提交。
⽤户接⼊TCC,最重要的是考虑如何将⾃⼰的业务模型拆成两阶段来实现。
例如:账户业务服务,将业务划分为资源(余额)检查与预留阶段与执⾏扣款或回滚阶段。
Try ⽅法作为⼀阶段准备⽅法(做资源的检查和预留)
在扣钱场景下,Try 要做的事情是就是检查账户余额是否充⾜,预留转账资⾦,预留的⽅式就是冻结 A 账户的转账资⾦。
Try ⽅法执⾏之后,账号 A 余额虽然还是 100,但是**其中 10 元已经被冻结了,不能被其他事务使⽤**。
⼆阶段 Confirm ⽅法(执⾏真正的扣钱操作)
Confirm 会使⽤ Try 阶段冻结的资⾦,执⾏账号扣款。Confirm ⽅法执⾏之后,账号 A 在⼀阶段中冻结的 10 元已经被扣除,账号 A
余额变成 70 元。
spring roll怎么读如果⼆阶段是回滚的话,就需要在 Cancel ⽅法内释放⼀阶段 Try 冻结的 10 元,使账号 A 的回到初始
状态,100 元全部可⽤需要注意的是,第⼆阶段 confirm 或 cancel 操作本⾝也是满⾜最终⼀致性的过程,在调⽤ confirm 或 cancel 的时候也可能因为某种原因(⽐
如⽹络)导致调⽤失败,所以需要活动管理⽀持重试的能⼒,同时这也就要求 confirm 和 cancel 操作具有幂等性(所谓幂等,就是任意多次执⾏所产⽣的影响均与⼀次执⾏的影响相同)。如果业务服务向 TCC 服务框架提交confirm/cancel 失败,不会导致不⼀致,因为服务最后都会超时⽽取消。TCC的实现框架有很多成熟的开源项⽬,⽐如tcc-transaction。它通过@Compensable切⾯进⾏拦截,可以透明化对参与者confirm/cancel ⽅法的调⽤,从⽽实现TCC模式
补偿模式
除了重试机制,还可以在每次更新时进⾏修复。定时校对也是⼀种重要的解决⼿段。业内⽐较常⽤的有单机场景下的Quartz以及分布式场景下的XXL-JOB等。
可靠事件模式
可靠事件模式是指通过引⼊可靠的消息队列,只要保证当前的可靠事件投递并且消息队列确保事件传递⾄少⼀次,那么订阅这个事件的消费者保证事件能够在⾃⼰的业务内被消费即可。但是在⽹络通信过程中,上下游可能因为各种原因⽽导致消息丢失。因此,需要通过“正反向消息机制”确保消息队列实现可靠的事件传递,并且使⽤补偿机制尽可能在⼀定时间内将未完成的消息重新投递。
⼀般做法,是主业务服务将要发送的消息持久化到本地数据库中,设置标志状态为“待发送”;然后把消息发送给消息队列,消息队列收到消息后,也把消息持久化到其存储服务中,但并不是⽴即向从业务服务(⽣产者)投递消息,⽽是先向主业务服务(⽣产者)返回消息队列的响应结果,然后主业务服务判断响应结果执⾏之后的业务处理。如果响应失败,则放弃之后的业务处理,设置本地的持久化消息标志状态为“结束”状态。否则,执⾏后续的业务处理,设置本地的持久化消息标志状态为“已发送"状态。
Apache RockerMQ
Apache RockerMQ是阿⾥开源的分布式消息中间件,4.3版本正式⽀持分布式事务消息。RockerMQ事务消息中间件解决了⽣产者端的消息发送与本地事务执⾏的原⼦性问题。换句话说,本地事务执⾏不成功,则不会进⾏MQ消息推送。
MQ消息、DB操作⼀致性⽅案:
1)发送消息到MQ服务器,此时消息状态为SEND_OK。此消息为consumer不可见。
2)执⾏DB操作;DB执⾏成功Commit DB操作,DB执⾏失败Rollback DB操作。
3)如果DB执⾏成功,回复MQ服务器,将状态为COMMIT_MESSAGE;如果DB执⾏失败,回复MQ服务器,将状态改为
ROLLBACK_MESSAGE。注意此过程有可能失败。
4)MQ内部提供⼀个名为“事务状态服务”的服务,此服务会检查事务消息的状态,如果发现消息未COMMIT,则通过Producer启动时注册的TransactionCheckListener来回调业务系统,业务系统在checkLocalTransactionState⽅法中检查DB事务状态,如果成功,则回复
COMMIT_MESSAGE,否则回复ROLLBACK_MESSAGE
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论