分布式事务,基于MQ实现最终一致性分布式事务

什么是分布式事务

传统的事务是基于项目耦合并且是单数据库的本地事务,简单的来说,分布式事务就是实现跨服务器和数据库的事务支持

CAP 定理,又被叫作布鲁尔定理。对于设计分布式系统(不仅仅是分布式事务),CAP 就是你的入门理论
C (一致性):对某个指定的客户端来说,读操作能返回最新的写操作。
对于数据分布在不同节点上的数据来说,如果在某个节点更新了数据,那么在其他节点如果都能读取到这个最新的数据,那么就称为强一致,如果有某个节点没有读取到,那就是分布式不一致。
A (可用性):非故障的节点在合理的时间内返回合理的响应(不是错误和超时的响应)。可用性的两个关键一个是合理的时间,一个是合理的响应。
合理的时间指的是请求不能无限被阻塞,应该在合理的时间给出返回。合理的响应指的是系统应该明确返回结果并且结果是正确的,这里的正确指的是比如应该返回 50,而不是返回 40。
P (分区容错性):当出现网络分区后,系统能够继续工作。打个比方,这里集群有多台机器,有台机器网络出现了问题,但是这个集群仍然可以正常工作。

MQ消息中间件的事务控制

首先MQ众所周知的作用在于请求削峰和系统解耦,在分布式系统中一个业务请求可能涉及多个服务,根据RPC木桶理论(整体耗时取决于响应最慢的接口),那么在引入MQ消息中间件后,可以很好的解决这个问题,业务请求完成本身的逻辑后返回,由MQ通过队列方式调用其它服务.
在这里插入图片描述
对于MQ控制事务,就必须开启MQ事务,MQ客户端使用事务,必须在session.close()之前必须执行session.conmmit()进行提交,同时可以使用try/cat异常中使用session.rollback()对当前消息进行回滚

使用MQ消息中间件的解决方案

概念介绍

最终一致性
MQ是一种最终一致性的分布式事务,就是说它保证的是消息最终一致性,而不是像2PC、3PC、TCC那样强一致分布式事务,至于为什么说它是最终一致性事务下面会详细说明。
Half Message(半消息,通过MQ的事务控制,消息必须conmit才能提交)
是指暂不能被Consumer消费的消息。Producer 已经把消息成功发送到了 Broker 端,但此消息被标记为暂不能投递状态,处于该种状态下的消息称为半消息。需要 Producer
对消息的二次确认后,Consumer才能去消费它。
消息回查
由于网络闪段,生产者应用重启等原因。导致 Producer 端一直没有对 Half Message(半消息) 进行 二次确认。这是Brock服务器会定时扫描长期处于半消息的消息,会
主动询问 Producer端 该消息的最终状态(Commit或者Rollback),该消息即为 消息回查。

分布式事务交互流程

理解阿里官方的图,就能理解MQ分布式事务的原理了。
在这里插入图片描述

  • 在系统A处理任务A前,首先向消息中间件发送一条消息,如果MQ发送失败直接取消操作
  • 消息中间件收到后将该条消息持久化,但并不投递(未conmmit提交)。此时下游系统B仍然不知道该条消息的存在
  • 消息中间件持久化成功后,便向系统A返回一个确认应答(传递到MQ消息队列,等待Conmiit)
  • 系统A收到确认应答后,则可以开始处理任务A的本地事务
  • 任务A处理完成后,向消息中间件发送Commit请求。该请求发送完成后,对系统A而言,该事务的处理过程就结束了,此时它可以处理别的任务了
  • 消息中间件收到Commit指令后,便向系统B投递该消息,从而触发任务B的执行
  • 当任务B执行完成后,系统B向消息中间件返回一个确认应答,此时,这个分布式事务完成
    从上面流程可以得知只有A服务本地事务执行成功 ,B服务才能消费该message

面试问题:

为什么要先发送Half Message(半消息):

  • 若系统A在处理任务A时失败,那么就会向消息中间件发送Rollback请求。系统A发完之后便可以认为回滚已经完成,它便可以去做其他的事情
  • 消息中间件收到回滚请求后,直接将该消息丢弃不投递给系统B

为什么说MQ是最终一致性事务
可能存在的情况: A事务执行成功,B事务执行失败
上面所介绍的Commit和Rollback都属于理想情况,但在实际系统中,Commit和Rollback指令都有可能在传输途中丢失。那么当出现这种情况的时候,消息中间件是如何保证数据一致性呢?——答案就是超时询问机制。

系统A除了实现正常的业务流程外,还需提供一个事务询问的接口,供消息中间件调用。当消息中间件收到一条事务型消息后便开始计时,如果到了超时时间也没收到系统A发来的Commit或Rollback指令的话,就会主动调用系统A提供的事务询问接口询问该系统目前的状态。该接口会返回三种结果:

  • 提交CommitTransaction:若获得的状态是“提交”,则将该消息投递给系统B
  • 回滚RollbackTransaction:若获得的状态是“回滚”,则直接将条消息丢弃
  • 处理中Unknow:若获得的状态是“处理中”,则继续等待

投递过程的可靠性保证
我们知道当上游系统A发出commit请求之后认为事务已经完成,便可以处理其他的任务了;那么消息中间件是怎么保证消息一定会被下游系统B成功消费呢?这是使用消息中间件投递过程的可靠性来保证的

消息中间件向系统B投递完消息后便进入阻塞等待状态,如果消息在传递过程中丢失或者消息的确认应答在返回途中丢失,那么消息中间件在等待超时后会重新投递(重试机制)直到消息被系统B成功消费为止,多次重试失败后,也没有关系,将该异常记录下来,由人工处理,人工兜底处理后,就可以让事务达到最终的一致性。

发布了32 篇原创文章 · 获赞 53 · 访问量 2469

猜你喜欢

转载自blog.csdn.net/qq_41714882/article/details/104324767
今日推荐