背景
在 《微服务下的一致性解决方案一》中已经提到过2阶段提交协议,但是并不完善,后面改进的三阶段提交也是存在弊端,下面介绍另一种基于MQ的二阶段提交方式。
可靠消息的最终一致性
可靠消息的最终一致性其本质也是利用MQ实现的二阶段提交方式,此方案设计三个模块:
上游业务执行并发送mq消息
可靠消息服务和MQ消息组件,协调上下游业务的执行,并保证数据的一致性
架构示意图
服务调用时序图
上游执行业务并发送消息到MQ 为第一阶段
时序图中的1,2,3,4,5,6,7可以被划分为第一阶段
1 上游业务通过RPC或者其他的方式发送消息给可靠消息服务
2 可靠消息服务存储消息,并将消息的状态改为已确认。
3 返回结果给上游服务
4 上游服务执行业务,
5 上游服务通过RPC或者其他方式通知可靠消息服务。
6 修改消息为已发送
7 发送消息到MQ,以便下游服务监听消息执行业务
以上的每一步都有可能出现失败的情况,分析一下这5步出现异常之后上游业务和消息发送是否一致。
失败步骤 | 现象 | 一致性 |
---|---|---|
第一步 | 上游业务未执行,MQ消息未发送 | 第一阶段一致 |
第二步 | 上游业务未执行,MQ消息未发送 | 第一阶段一致 |
第三步 | 上游业务未执行,MQ消息未发送 | 第一阶段一致 |
第四步 | 上游业务已经执行,MQ消息未发送 | 第一阶段不一致 |
第五步 | 上游业务已经执行,MQ消息未发送 | 第一阶段不一致 |
第六步 | 上游业务已经执行,MQ消息未发送 | 第一阶段不一致 |
第七步 | 上游业务已经执行,MQ消息未发送 | 第一阶段不一致 |
上游业务已经执行完成,下游业务未执行或者是执行失败的时候,此事务即为BASE理论中的Soft State状态。
下游监听MQ消息并执行业务,为第二阶段
时序图中的8,9,10,11,12可以划分为第二个阶段。
8 下游监听MQ消息组件并获取消息
9 下游应用根据MQ消息体消息处理本地业务
10 下游ACK确认消息被消费
11 下游通知消息服务,告知已完成业务。
12 修改消息为已完成
以上的每一步都有可能出现问题,分析一下上面出现问题的步骤
失败步骤 | 现象 | 一致性 |
---|---|---|
第八步 | 下游业务未执行,消息状态为发送 | 第二阶段 一致 |
第九步 | 下游业务如果回滚,消息状态为发送 | 第二阶段 一致 |
第九步 | 下游业务如果执行,消息状态为发送 | 第二阶段 一致 |
第十步 | 下游业务如果执行,消息状态为发送 | 第二阶段 不一致 |
第十一步 | 下游业务如果执行,消息状态为发送 | 第二阶段 不一致 |
第十二步 | 下游业务如果执行,消息状态为发送 | 第二阶段 一致 |
通过分析第一阶段和第二阶段可能失败的情况,为了确保上下游数据的最终一致性,需要在可靠消息服务中开发消息状态确认和消息重发两个功能以实现BASE理论的最终一致性。
可靠消息服务定时的监听消息的状态,如果存在状态为待确认并且超时的消息,则标识上游应用和可靠消息交互真能干的步骤4,5,6,7可能出现问题,可靠消息服务需要携带消息往上游追溯是否已经执行成功(上游业务应该提供共一个可查询的接口供可靠消息服务追溯消息状态),如果业务执行成功,则更改消息状态为已发送,否则删除消息确保数据一致。
上游追溯
可靠消息已经发送则表示应用已经执行,接下来则确保下游应用也能正常执行。
可靠消息服务中如果发现消息为已发送并且超时的消息,则表示可靠消息服务和下游的应用中存在异常的步骤,无论是哪一个步骤出现异常,可靠消息服务都将次消息重新投递到MQ组件中供下游监听。
下游应用监听到此消息后,在保证幂等性的情况下执行业务并通知可靠消息服务此消息已经成功消费,最终更确保上游应用个,下游应用的数据保证一致性,具体的流程为:
下游消息确认
可靠消息服务定时查询消息已经发送并且超时的消息
可靠消息将重新投递到MQ组件中
下游应用通知可靠消息服务已经成功消费
通过消息装填确认和消息重发两个功能,可以保证上游应用、可靠消息服务和下游应用的最终一致性。
但是在实际应用中,还是需要引入人工的干预,比如重发机制(包括重发的次数等)问题。
作者:介鬼
链接:https://www.jianshu.com/p/11e4166ed669