基于消息中间件,图解柔性事务一致性

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 在核心业务处理完成之后,发送消息通知,允许失败,在指定时间段内或者指定重试次数之后,允许消息丢失情况存在,即消息的不可靠性。

一、最大努力通知

TCC分段提交适用分布式架构中对一致性、实时性要求较高的业务场景,在实际业务中也存在实时性比较低的业务,例如常见的短信通知,客户端消息,运营体系更新等业务,这时候为了减轻核心流程的复杂度和压力,可以采取最大努力通知方式实现柔性事务的管理。

11-1.png

例如常见的第三方支付业务中,本地业务和支付端业务处理完成之后都会生成消息通知,基本流程如下:

  • 本地业务预处理完成之后;
  • 请求第三方支付服务;
  • 支付操作成功对该账号发送消息;
  • 支付服务回调本地业务;
  • 本地业务生成系统通知消息;

上述流程的消息场景中有一些基础特点,在核心业务处理完成之后,发送消息通知,允许失败,在指定时间段内或者指定重试次数之后,允许消息丢失情况存在,即消息的不可靠性。

在实际的支付系统中,启动每日对账校验时会对当日的流水做校验,如果发现支付流水有未完成的流程,会有状态弥补,后续可以继续处理,这种手段在对账中很常用。

二、可靠消息

分布式事务基于可靠消息最终一致性的实现方案,既然是可靠消息,则要求MQ必须支持事务管理,这样才能保证业务前后一致性。

1、RocketMQ事务消息

RocketMQ在4.3版中开始支持分布式事务消息,采用2PC的思想来实现了提交事务消息,同时增加一个补偿逻辑来处理二阶段超时或者失败的消息,如下图所示:

11-2.png

上图说明了事务消息的大致方案,其中分为两个流程:正常事务消息的发送及提交、事务消息的补偿流程。

1.1 发送及提交

(1)发送消息(half消息,即发送但不被消费);

(2)服务端响应消息写入结果;

(3)根据发送结果执行本地事务,如果写入失败,此时half消息对业务不可见,本地逻辑不执行;

(4) 根据本地事务状态执行Commit或者Rollback(Commit操作生成消息索引,消息对消费者可见)

1.1 补偿流程

(1)对没有Commit/Rollback的事务消息(pending状态的消息),从服务端发起一次“回查”;

(2)Producer收到回查消息,检查回查消息对应的本地事务的状态;

(3)根据本地事务状态,重新Commit或者Rollback;

其中,补偿阶段用于解决消息Commit或者Rollback发生超时或者失败的情况。

1.3 设计原理

在RocketMQ事务消息的主要流程中,一阶段的消息如何对用户不可见。其中,事务消息相对普通消息最大的特点就是一阶段发送的消息对用户是不可见的。那么,如何做到写入消息但是对用户不可见呢?RocketMQ事务消息的做法是:如果消息是half消息,将备份原消息的主题与消息消费队列,然后改变主题为RMQ_SYS_TRANS_HALF_TOPIC。由于消费组未订阅该主题,故消费端无法消费half类型的消息,然后RocketMQ会开启一个定时任务,从Topic为RMQ_SYS_TRANS_HALF_TOPIC中拉取消息进行消费,根据生产者组获取一个服务提供者发送回查事务状态请求,根据事务状态来决定是提交或回滚消息。

2、最终一致性

基于上述RocketMQ事务消息可靠性的特点,即可以实现某类业务下事务的最终一致性。消息发送一致性是指产生消息的业务动作与消息发送一致,也就是说如果业务操作成功,那么由这个业务操作所产生的异步消息一定要发送出去,否则就业务失败回滚,消息也会丢弃。

流程基本如下:

11-3.png

  • 发送half事务消息,无法被消费;
  • 本地业务代码逻辑处理完成;
  • 发送确认消息,标识该消息可以消费;
  • 如果消息生产方异常,取消整体动作;

该流程主要针对消息生产方,在实际开发中,消息的消费方也一样很难处理,要保证最终一致性,必然会面对一个问题,消费方异常,消息不断的重试,可能存在部分业务处理成功,部分业务处理失败的情况,这时候就要解决服务接口的幂等性问题。

三、幂等接口

1、幂等简介

编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。就是说,一次和多次请求某一个资源会产生同样的作用影响。

11-4.png

在复杂的异步流程中,尤其注意失败重试问题,通常支付流程中,每次接口被请求,对每一步数据更新的操作,都会前置一步状态查询的流程,用来判断下一步的数据更新是否该执行。

2、幂等接口

在系统服务接口请求中,任何明确的接口响应,例如失败或成功,这样业务流程都好处理,但是例如支付场景如果请求超时,如何判断服务的结果状态:客户端请求超时,本地服务超时,请求支付超时,支付回调超时,客户端响应超时等,或者基于MQ的不断重试机制,在部分业务异常状态下,始终没有返回成功,则消息会一直重试。

这就需要设计流程化的状态管理,尤其在消息重试机制下,很少会再次对重试的业务接口使用重度的事务控制,有些业务被执行完毕,只需要判断一个状态,下次消息重试跳过即可,只需要把未处理的业务补偿处理即可,在重试机制下,在部分业务没有全部执行成功之前,消息会一直重试,直到最终全部完成。

相关实践学习
RocketMQ一站式入门使用
从源码编译、部署broker、部署namesrv,使用java客户端首发消息等一站式入门RocketMQ。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
相关文章
|
5月前
|
缓存 NoSQL 关系型数据库
【中间件】Redis与MySQL双写一致性如何保证?--缓存和数据库在双写场景下一致性是如何保证的
【中间件】Redis与MySQL双写一致性如何保证?--缓存和数据库在双写场景下一致性是如何保证的
132 0
【中间件】Redis与MySQL双写一致性如何保证?--缓存和数据库在双写场景下一致性是如何保证的
|
5月前
|
算法 NoSQL Java
2023年阿里高频Java面试题:分布式+中间件+高并发+算法+数据库
又到了一年一度的金九银十,互联网行业竞争是一年比一年严峻,作为工程师的我们唯有不停地学习,不断的提升自己才能保证自己的核心竞争力从而拿到更好的薪水,进入心仪的企业(阿里、字节、美团、腾讯.....)
|
9月前
|
NoSQL Java Redis
阿里Java高级岗中间件二面:GC+IO+JVM+多线程+Redis+数据库+源码
虽然“钱多、事少、离家近”的工作可能离技术人比较远,但是找到一份合适的工作,其实并不像想象中那么难。但是,有些技术人确实是认真努力工作,但在面试时表现出的能力水平却不足以通过面试,或拿到高薪,其实不外乎以下 2 个原因:
|
9月前
|
算法 NoSQL Java
2023年阿里高频Java面试题:分布式+中间件+高并发+算法+数据库
又到了一年一度的金九银十,互联网行业竞争是一年比一年严峻,作为工程师的我们唯有不停地学习,不断的提升自己才能保证自己的核心竞争力从而拿到更好的薪水,进入心仪的企业(阿里、字节、美团、腾讯.....)
|
9月前
|
算法 NoSQL Java
2021年阿里高频Java面试题:分布式+中间件+高并发+算法+数据库
又到了一年一度的金九银十,互联网行业竞争是一年比一年严峻,作为工程师的我们唯有不停地学习,不断的提升自己才能保证自己的核心竞争力从而拿到更好的薪水,进入心仪的企业(阿里、字节、美团、腾讯.....)
|
10月前
|
消息中间件 安全 Java
全网首发!消息中间件神仙笔记,涵盖阿里十年技术精髓
消息中间件是分布式系统中的重要组件,在实际工作中常用消息中间件进行系统间数据交换,从而解决应用解耦、异步消息、流量削峰等问题,实现高性能、高可用、可伸缩和最终一致性架构。
|
10月前
|
消息中间件 数据采集 Java
开发神技!阿里消息中间件进阶手册限时开源,请接住我的下巴
相信大家在实际工作中都用过消息中间件进行系统间数据交换,解决应用解耦、异步消息、流量削峰等问题,由此消息中间件的强大功能想必也不用我多说了!目前业界上关于消息中间件的实现多达好几十种,可谓百花齐放,所用的实现语言同样也五花八门。不管使用哪一个消息中间件,我们的目的都是实现高性能、高可用、可伸缩和最终一致性架构。
|
12月前
|
缓存 NoSQL 容灾
《Java应用提速(速度与激情)》——六、阿里中间件提速
《Java应用提速(速度与激情)》——六、阿里中间件提速
|
12月前
|
消息中间件 NoSQL Dubbo
阿里Java高级岗中间件二面:GC+IO+JVM+多线程+Redis+数据库+源码
一转眼,都2023年了,你是否在满意的公司?拿着理想的薪水? 虽然“钱多、事少、离家近”的工作可能离技术人比较远,但是找到一份合适的工作,其实并不像想象中那么难。但是,有些技术人确实是认真努力工作,但在面试时表现出的能力水平却不足以通过面试,或拿到高薪,其实不外乎以下 2 个原因: 第一,“知其然不知其所以然”。做了多年技术,开发了很多业务应用,但似乎并未思考过种种技术选择背后的逻辑。所以,他无法向面试官展现出自己未来技术能力的成长潜力。面试官也不会放心把具有一定深度的任务交给他。 第二,知识碎片化,不成系统。在面试中,面试者似乎无法完整、清晰地描述自己所开发的系统,或者使用的相关技术。
2023年阿里高频Java面试题:分布式+中间件+高并发+算法+数据库
又到了一年一度的金九银十,互联网行业竞争是一年比一年严峻,作为工程师的我们唯有不停地学习,不断的提升自己才能保证自己的核心竞争力从而拿到更好的薪水,进入心仪的企业(阿里、字节、美团、腾讯.....)