多类型业务消息专题-顺序消息 | 学习笔记

简介: 快速学习多类型业务消息专题-顺序消息

开发者学堂课程【 RocketMQ 消息集成:多类型业务消息专题多类型业务消息专题-顺序消息】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址https://developer.aliyun.com/learning/course/1161/detail/17326


多类型业务消息专题-顺序消息

 

内容介绍:

一、   背景介绍:顺序消息简介

二、   功能原理:顺序消息的原理及实现

三、   最佳实践:顺序消息的最佳实践及案例

四、   实战:顺序消息收发样例

 

一、   背景介绍:顺序消息简介


Rocker MQ 提供一种对消息发送和销售严格要求的消息,具体来说,就是在一个指定 Topic ,它会对同一个 MessageGroup 按照严格的发货顺序来进行发。不和消费就是严格的先进先出顺序,同一个 group 消息保证顺序而不同,MessageGroup 这顺序则不作要求,因此实际上可以看到,这地方实际上是一个一个偏序。可以看到以下图 producer 发送消息,A1,A2,A3,这里的 AB,指的是MessageGroup A MessageGroup B ,就是 A1A2 是一组,B1B2 也是另外一组, consumer 就按照这两组。但并且会按照组内的顺序来进行消费。


image.png


可以看到其实发送的顺序主要就是包括两块,一个就是发送一个是消费按照这两块来展开,在开始详细介绍这些消息的发送消费之前,首先了解它的一个生命周期,它的生命周期其实跟普通消息比较类似它都是包括五点,初始化消费,消费中,消费提交,消费删除,初始化顺消息被生产者构建初始化完成,待发送服务端的状态,初始化消费,指的是当服务端已经被发送到并且发送,并且被存储到服务端时,此时这条消息对下游的消费者是可见的一个状态。消费中,指的是消息已经被消费者拉取,并且按照用户自定义的一个业务逻辑的进行处理,此时服务端会等待,处理结果就是消费完成。如果一段时间后没有收到消费提交的事件,消息还会进行一个重置,也就是保证了消息的 atleastonce 的语义。接下来,是消息提交。当消费者完成消费处理时,会提交一个消费应答试点到服务端,服务端会标记该消息已经被处理。值得注意的是就支持保留此时这消息并不会立刻被删除,只是在逻辑上,消费完成的。消费删除,指的是 Rocker MQ 会按照消息的保证时间来去滚动清理最早的效率数据。比方超过三天就会从存储设备进行删除。这里具体的与普通消息不同的点就在于它是一条,或者一批的被拉取到客户,达到客户端。当前一批消息没有被完全处理后一批消息并不能被推送到消费者,也就是拉取或者推送是取决于一个消费完成一个结果的。


image.png


二、   功能原理:顺序消息的原理及实现


顺序消息的发送。谈到顺序消息发送,首先可以谈一下在分布式环境下一个顺序的概念。一个环境下保证消息的一个全局顺序的困难。举个例子来说,Rocker MQ 消息发送者有 Producer A Producer B,在没有沟通的情况下,各自向服务端向同一个服务端发送消息B,是没办法定义消息A和消息B的顺序。不能AB之前或者B A B 之后,或者只是对于客户来说是未知的,因此在这一个情况下,保证的往往是一个分区的,相对的顺序性,保证带有同一属性的消息的顺序,会把同一属性的分为一个组,将该属性称之为 MessageGroup 。如下图所示,Produce A 会发送 A1 A2 B1 B2,也就是两个 MessageGroupa B 的四条消息,而 produce B 会发送两个 C1 C2


image.png


对于同一个 Message ,首先会保证 MessageGroup 下顺序的先后性,为了保证顺序性,这里其实产生了一个比较简单的做法,也是构造一个单线程的场景。比如不同的 APP 有不同的 Linux,或者不同线程下一个 produce 来进行处理,对于同一个 producer 而言,它会同步的去发送同一个 MessageGroup 。同步的发送的好处是显而易见的,在客户端先发送一条 A1,在它没有得 A 这条消息的发送,结果当它得到这条发送结果之后,才会去发动下一条,也就是通过发送结果,服务端返回给客户端发送结果,实际上,客户端就知道了 A1 A2 的一个逻辑关系,也就是可以定义此时如果 A2 发送成功了,A2 就是 A1 之后,实际上是可以通过一个同步发送,一个沟通智能的去保证了发送的顺序性。同时也能看到在发动场景下MessageGroup 的好处。MessageGroup 实际上是提高了它的一个并发程度和一个可拓展性,就是限制呢只是对同一个 MessageGroup 需要做一个限制向不同的MessageGroup 比如 MessageGroup A MessageGroup B 显然不需要MessageGroup A ,MessageGroup B 因此可以看到,虽然在底层原理上,普通消息的发送和消费,消息的发送,实际上并没有什么区别,但是为了保证一个顺序的语义,所以实际上是通过一个统一 MessageGroup 下同步发送的一个同步发送的一个方式,实际上,一定程度相比较普通消息。隐式的降低了的一个最大的一个吞吐量。


image.png


接下来可以了解顺序的消息的消费需要保证同一时刻就一个客户端,或者只有一个客户端的一个线程来去消费同一个 MessageGroup 下的消息。并且在该条消息被确认消费完成之前,当然进入消费失败的情况,也是定义的一种消费完成,在消费完成之前消费者是无法消费同一个 mac 下一条消息,如果能够异步并发去消费后面的消息,消息的顺序就会得到保证了,要是要先消费第一条再消费第二条,如图所示:


image.png


consumer 比方有两个线程,它会分别去消费 MessageGroup C, MessageGroup D,可以看到 C D 之间,其实是一个异步并发消费,因为并不存在一个顺序的关联性。所以也可以看到,可以在这里再次看到它。其实这里提到一个顺序,一个MessageGroup 下的顺序,实际上是一个偏序。如果拿普通线程来进行对比,普通线程,实际上对消费其实没有任何的限制,都是完全的异步并发的,剩下的顾名思义设计的特点,必须要保证先后顺序消费的一个语义。


image.png


可以做个总结,就是发送消费。特别消费和普通代理做一个对比,如表格。首先是原子性,原子性普通消息,是消息,没有任何关联关系,顺序消息和普通消息之间存在一个偏序关系,就是同一个 MessageGroup 下,保证一个顺序。顺序效率当然是严格有序的,普通消息实际上会有保证一个大概有序,但是大致有序,是没有严格保证,在一些情况下会被破坏掉。

 

第二是可靠性,由于之前提到的一个 MessageGroup 的一个限制,可扩展性相比较普通还是较差,但是由于不同 MessageGroup 之间是没有一个逻辑关系的,所以还是能够具备一定的可扩展性。吞吐:其实理论上,顺序消息的吞吐量挺高的,实际上刚才提到的一个发送和消费的一个介绍,可以看到交易吞吐量实际上是受到它收发的一个限制,发送就是同步发送限制消费,是取决于用户自身的一个消费逻辑,如果用自身消费逻辑卡的比较久,它的消费能力也会受到一定的限制,然后普通消息,由于它没有任何的一个突破逻辑和关联关系,所以程度是较高的。

 

接下来是并发单元,可以看到顺序消息的一个并发单元,实际上就是同一个MessageGroup 或同一组 MessageGroup 是一个单元,就是一个 MessageGroup下,是一个单线程的,而普通可以看到,可以认为普通消息的并发基本单元是单条消息,或者它是一种特殊的,每条消息都有不同的 MessageGroup 消息,它是一种特殊的消息。因此综上所述,普通消息,顺消息其实对用户的编编码要求会比较高,对于普通消息则相对较低,之所以这么可以后面结合的案例和最佳实践来做一个具体的看,这里编码要求实际上更多的是指的一些。这是一个 MessageGroup 的选择,以及消费逻辑的一个设计。最后在功能原理上做个总结,无论对于发送来消费,都会通过 MessageGroup 来将稍微进行分组,分组实际上是构建了一个单线程的一个环境。来保证消息的发送消费的一个顺序性,其实也就是实际上也是构建了一个逻辑上的先入先出一个分子概念。然后剩余消息的并发基本是MessageGroup 不同 MessageGroup 可以并发的发送和消费从而一定程度的具备的可拓展性,也就是一定程度的支持多队列存储,水平拆分支持并发消费,并且可以是不受影响

 

三、   最佳实践:顺序消息的最佳实践及案例


image.png


做完了一个功能和原理的介绍,接下来看到最佳实践,首先,来看两个比较经典的一个案例,首先第一个就是用户一个注册,用户注册需要发送验证码,验证码比方用户 ID 来做一个 MessageGroup 。同一个用户发送的消息都会按照发布的先后来消费,比方先注册,然后再登录,就会有一个发布的先后顺序,当然不同的用户之间的顺序当然是无所谓的,因为用户 ID 其次是一个订单的一个电商的一个订单创建,如图也可以看出来。假设订单 ID 做个 MessageGroup ,同一个订单相关的创建,支付退款,物流,当然是一个逻辑关系,它的顺序都会按照发布的消费来消费。

 

提到这里可以看到一个最佳实践了,首先就是需要合理的去设置 MessageGroup ,在实际的 case 上? MessageGroup 会有很多错误的选择。为什么这么说?以某电商平台的一个使用为例,某电商平台,会加商家的 ID 作为 MessageGroup 。可以看到商家规模是有大有小的部分规模较大的商家,会产生较多订单,这批较多订单就会强行保证一个顺序,由于下游的一个消费者的一个限制。要一条一条进行处理,这部分商家对应订单就会发生严重的堆积。问题出在哪里?我们并不能够将商家的 ID 作为 MessageGroup ,应当来将订单号来做 MessageGroup ,而且站在背后的业务逻辑上,本来就是同一个订单才有一个顺序要求,同一个商家上面的不同订单,它实际上是可以并发去进行处理。因此可以看到这里选择合理选择 MessageGroup 如何去合理选择?首先就是 MessageGroup 的生命周期会比较短暂,举个例子,比如订单 ID ,它是一个比如持续一段时间。还有一点就是不同的MessageGroup 的数量应该尽量均衡,也就是数量不能差太多,像之前的错误,Case 商家 ID 显然不适合做一个合理的 MessageGroup ,因为它的 MessageGroup 的数量会差比较多,比如较大的商家不同 MessageGrou 的消息比较多。其次也提到一定要使用同步发送和发送重试,使用同步发送,才能保证统一MessageGroup 的消息是能够同时发送。如果使用异步发送或者使用说多线程发送,实际上是不能保证发送顺序性的。其次重试放大也非常重要,如果不做发送重试,消费时代不经意处理,当然消息都未能成功的发送到服务端,也就无从保证发生的顺序性。最后就消费密等,相信程度可能会出现少量重复,如果业务不能正常的去处理重复。

 

顺序可能会得到,会被破坏,因此业务消费首先做好消费密等,免冲突处理带来一些风险所以可以看到。顺序消息并不是表面上看到的,它是一个普通的一个完全加强版,实际上它是在普通消息上面是做了一定的取舍和权衡的,是做一个 trade off ,因此还是要合理的根据自己的业务场景来去对应的消息系列来进行一个选型。而且可以看到,对于在用户的编码上也有比较高的要求,也比方不能错误的使用一些异步发送了,还有消费逻辑也要也要注意,因为如果一旦一个消费逻辑卡住的话,那么同一 MessageGroup 下的顺序,也就是同一顺序组下面后续消息都会同样被卡住,因此就会进而会造成一些影响消费,影响消费,影响吞吐量的一些后果。

 

四、   实战:顺序消息收发样例

image.png

最后来看 case,也就是发送和消费的样例,首先是发送的样例,看到这例子上,首先设置了一个配置。其次设置了对应的 topic 。最重要的是设置核心概念MessageGroupMessageGroup 来决定了消息的顺序。可以看到这里采用的是一个同步发送它,客户端拿到服务端,响应的结果之后,它才会进行下一步的处理。


image.png


接下来是一个顺消费样例。首先进行拉取,拉取完实际上这里的业务逻辑是被忽略掉,应该在 APP 之前,就是拉取消息,然后并且对消息来进行逐条的一个处理。是一条一条处理,处理之后拿到消息,然后会进入一个业务处理的一个线程,就是丢到自己的业务处理逻辑里,当处理完之后,会出现一个 APP ,就是一个确认逻辑,标记这条消息已经正常的被消费,整个流程就完成了。

相关文章
|
7月前
|
人工智能 自然语言处理 BI
基于阿里云人工智能平台的智能客服系统开发与部署
随着人工智能技术的发展,智能客服系统成为企业提升服务效率和用户体验的重要工具。阿里云提供包括自然语言处理(NLP)、语音识别(ASR)、机器学习(PAI)等在内的完整AI平台,助力企业快速构建智能客服系统。本文将通过电商平台案例,展示如何基于阿里云AI平台从零开始开发、部署智能客服系统,并介绍其核心优势与最佳实践,涵盖文本和语音客服、知识库管理及数据分析等功能,显著提升客户服务效率和用户满意度。
|
9月前
|
缓存 Java 测试技术
分享干货:idea常用快捷键分类总结(适合速查~~建议收藏♥)
本文以分类的形式总结了IDEA常用、好用快捷键,全是干货~
2179 1
分享干货:idea常用快捷键分类总结(适合速查~~建议收藏♥)
|
9月前
|
缓存 Java Maven
【简单四步教你解决♥十分有效】Maven依赖报错、依赖或插件导入失败的万能解决办法
【简单四步教你解决♥十分有效】Maven依赖报错、依赖或插件导入失败的万能解决办法!在处理Maven项目问题时,首先检查Maven配置是否正确。接着通过“File--Invalidata Caches”清除IDEA缓存并重启。使用Maven命令`mvn dependency:purge-local-repository`和`mvn dependency:resolve`清除本地依赖缓存。最后,在Terminal中输入`mvn clean install`完成构建。
2567 1
【简单四步教你解决♥十分有效】Maven依赖报错、依赖或插件导入失败的万能解决办法
ly~
|
11月前
|
存储 Oracle 关系型数据库
数据库的优点和缺点分别是什么?
### 数据库的优点与缺点 数据库具有高数据共享性,允许多用户和多应用同时访问,提升信息流通效率。其数据一致性通过约束机制和事务管理保障,确保数据完整无误。数据库具备强数据独立性,改变存储结构或逻辑结构对应用影响小。此外,用户权限管理和数据加密提升了数据安全性。 然而,数据库也存在成本高的问题,包括软件购买与维护费用及高性能硬件需求。大规模数据处理可能导致性能瓶颈,尤其是在高并发场景下。数据迁移复杂,尤其是不同数据库系统间或版本升级时,需处理数据结构和语法差异。
ly~
1211 2
|
关系型数据库 分布式数据库 数据库
PolarDB-X源码解析:揭秘分布式事务处理
【7月更文挑战第3天】**PolarDB-X源码解析:揭秘分布式事务处理** PolarDB-X,应对大规模分布式事务挑战,基于2PC协议确保ACID特性。通过预提交和提交阶段保证原子性与一致性,使用一致性快照隔离和乐观锁减少冲突,结合故障恢复机制确保高可用。源码中的事务管理逻辑展现了优化的分布式事务处理流程,为开发者提供了洞察分布式数据库核心技术的窗口。随着开源社区的发展,更多创新实践将促进数据库技术进步。
260 3
|
消息中间件 程序员 调度
如何区分进程、线程和协程?看这篇就够了!
以下是内容摘要,已简化并保持在240字符以内: 嗨,我是小米!今天聊聊进程、线程和协程: - **进程**:资源分配基本单位,独立且隔离。 - **线程**:进程内执行单元,轻量级且共享资源。 - **协程**:比线程更轻量,适合I/O密集型任务。 每种都有独特特点和适用场景,选择合适可优化性能。希望对你有所帮助!更多内容,请关注我的公众号“软件求生”。
429 1
|
10月前
|
Prometheus 监控 Cloud Native
在 Java 中,如何使用线程池监控以及动态调整线程池?
【10月更文挑战第22天】线程池的监控和动态调整是一项重要的任务,需要我们结合具体的应用场景和需求,选择合适的方法和策略,以确保线程池始终处于最优状态,提高系统的性能和稳定性。
1632 2
|
运维 Prometheus 监控
「架构」云上自动化运维及其应用
企业在云上采用自动化运维,通过Prometheus+Grafana实现监控,Ansible进行配置管理,Jenkins+GitLab+SonarQube支持CI/CD,提升效率,降低成本。关键指标包括系统可用性、故障恢复时间等。通过自动化监控、配置管理和持续集成/部署,保证服务稳定性,促进快速迭代,确保市场竞争力。持续改进与培训是维持领先的关键。
353 0
ThreadPoolExecutor的中的submit和FutureTask || 通过Executors 创建线程池的一些实例(Callable和Runnable的在其中的体现)
ThreadPoolExecutor的中的submit和FutureTask || 通过Executors 创建线程池的一些实例(Callable和Runnable的在其中的体现)
328 0
|
JavaScript 前端开发 Windows
【异常解决】vue项目localhost:8080无法访问此网站或者无法访问此页面,localhost拒绝了我们的连接请求
【异常解决】vue项目localhost:8080无法访问此网站或者无法访问此页面,localhost拒绝了我们的连接请求
3506 0