消息队列如何确保消息的有序性?

标签: 消息队列 消息 | 发表时间:2021-05-15 01:32 | 作者:duysh
出处:https://juejin.cn/tag/%E6%9E%B6%E6%9E%84

要想实现消息有序,需要从 Producer 和 Consumer 两方面来考虑。

首先,Producer 生产消息的时候就必须要有序。

然后,Consumer 消费的时候,也要按顺序来,不能乱。

Producer 有序

像 RabbitMQ 这类普通的消息系统,队列结构简单,Producer 向队列中发送消息就完了,进入队列的消息肯定是有序的。

Kafka 比较特殊,因为它的一个 Topic(就是队列的概念)实际上分为了多个 Partition。

Producer 发送消息的时候,是分散在不同 Partition 的。

Producer 按顺序发消息,但进入 Kafka Topic 之后,这些消息就不一定进到哪个 Partition 了,所以顺序肯定是乱的。

如果想 Topic 内的消息 全局有序,就只能设置一个 Partition 了,这就变成了 RabbitMQ 那种结构。

但这种结构不符合 Kafka 的设计理念,Topic 只有一个 Partition 就失去了扩展性。

kafka 还支持一种 局部有序的方式,就是把某一类的消息都放入同一个 Partition,就保证了这组消息的顺序。

在发消息的时候指定 Partition Key,Kafka 对其进行 Hash 计算,根据计算结果决定放入哪个 Partition。

所以,Partition Key 一样的消息肯定是在一起的。

例如使用用户 ID 做 key,这样同一个用户的消息肯定是在一起的,就保证了这一组的消息的有序。

Consumer 有序

MQ 内消息有序,那么 Consumer 自然也是按顺序接收的。

但是,如果使用了多个 Consumer,就可能出现乱序。

例如 RabbitMQ 的一个 Queue 有 3个 Consumer,虽然会按顺序接收到消息,但是它们各自的处理速度是不同的,所以,出来的结果很可能是乱序的。

如果想严格按顺序来,就只能使用一个 Consumer。

如果可以使用局部有序,那么就把之前的一个队列拆为多个队列,就像 Kafka 的 Partition Key 一样,把同组数据放入同一个队列。

Kafka 中一个 Partition 只能对应一个 Consumer,但如果 Consumer 使用了多线程,就和多个 Consumer 一个效果了,还是会造成乱序。

这样的话就需要 进一步细化消息的分组。

为每个线程创建一个内存队列,Consumer 收到消息后,把同组的消息都放在同一个内存队列,由同一个线程处理即可。

小结一下,消息的有序需要 Producer 和 Consumer 都有序。

RabbitMQ 的队列结构简单,Producer 发送的消息是有序的。但 Kafka 特殊,一个 Topic 有多个 Partition,如果要求全局有序,就只能使用一个 Partition。

如果可以接受局部有序,就可以为消息设置 Partition Key,其 Hash 计算结果相同的消息都会在同一个 Partition。

Consumer 消费时需要注意多 Consumer 的情况,例如多个消费线程。

可以在 Consumer 收到消息后再细化分组,同组的消息交给同一个消费线程处理。

推荐阅读

OAuth2 图解

轻松理解 Kubernetes 的核心概念

开发者必须要了解的架构技术趋势:Service Mesh

相关 [消息队列 消息] 推荐:

快速的消息队列 SquirrelMQ

- Le - 开源中国社区最新软件
SquirrelMQ是一个快速的消息队列.   SquirrelMQ VS Redis 入队列: SquirrelMQ:100万条数据,105S,内存使用84MB. Redis:100万条数据,156S,内存使用127MB.   出队列:   SquirrelMQ:100万条数据,230S. Redis:100万条数据,163S.

Feed消息队列架构分析

- - Tim[后端技术]
最近一两年,大部分系统的数据流由基于日志的离线处理方式转变成实时的流式处理方式,并逐渐形成几种通用的使用方式,以下介绍微博的消息队列体系. 当前的主要消息队列分成如图3部分. 1、feed信息流主流程处理,图中中间的流程,通过相关MQ worker将数据写入cache、Redis及MySQL,以便用户浏览信息流.

redis作为消息队列的使用

- - ITeye博客
在redis支持的数据结构中,有一个是集合list. 对List的操作常见的有lpush  lrange等. 在这种常见的操作时,我们是把集合当做典型意义上的‘集合’来使用的. 往往容易被忽视的是List作为“队列”的使用情况. 反编译redis的jar包,会发现:.  pop意为“弹”,是队列里的取出元素.

高可用消息队列框架ZBUS

- - 企业架构 - ITeye博客
我们在日常开发中可以需要用到消息队列 当然我们完全可以自己写一个生产者-消费者框架 但是高可用性、实时性已经大量数据堆积时候就显得问题捉襟见肘了下面推荐的框架在我时间项目中和测试中都是非常不错那么他是什么框架呢.    zbus git地址. http://git.oschina.net/rushmore/zbus ZBUS=MQ+RPC 服务总线 1)支持消息队列, 发布订阅, RPC, 交易系统队列适配 2)亿级消息堆积能力、支持HA高可用 3)无依赖单个Jar包 ~300K 4)丰富的API--JAVA/C/C++/C#/Python/Node.JS多语言接入,支持HTTP等协议长连接入.

[转]消息队列的两种模式

- -
Java消息服务(Java Message Service,JMS)应用程序接口是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信. 点对点与发布订阅最初是由JMS定义的. 这两种模式主要区别或解决的问题就是发送到队列的消息能否重复消费(多订阅).

消息队列设计精要

- - 美团点评技术团队
消息队列已经逐渐成为企业IT系统内部通信的核心手段. 它具有低耦合、可靠投递、广播、流量控制、最终一致性等一系列功能,成为异步RPC的主要手段之一. 当今市面上有很多主流的消息中间件,如老牌的ActiveMQ、RabbitMQ,炙手可热的Kafka,阿里巴巴自主开发的Notify、MetaQ、RocketMQ等.

深入浅出 消息队列 ActiveMQ

- - 编程语言 - ITeye博客
ActiveMQ 是Apache出品,最流行的、功能强大的. 即时通讯和集成模式的开源服务器. ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现. 提供客户端支持跨语言和协议,带有易于在充分支持JMS 1.1和1.4使用J2EE企业集成模式和许多先进的功能.

延迟消息队列设计

- -
由于Kafka不支持延迟消息,而目前公司技术栈中消息中间件使用的是Kafka,业务方希望使用RocketMQ满足延迟消息场景,但如果仅仅只是需要延迟消息功能而引入多一套消息中间件,这会增加运维与维护成本. 在此背景下,我们希望通过扩展Kafka客户端提供延迟消息的支持. 本篇将介绍四种延迟消息实现方案的原理,以及分析其优缺点.

消息队列如何确保消息的有序性?

- - 掘金 架构
要想实现消息有序,需要从 Producer 和 Consumer 两方面来考虑. 首先,Producer 生产消息的时候就必须要有序. 然后,Consumer 消费的时候,也要按顺序来,不能乱. 像 RabbitMQ 这类普通的消息系统,队列结构简单,Producer 向队列中发送消息就完了,进入队列的消息肯定是有序的.

java多线程消息队列的实现

- - 编程语言 - ITeye博客
2、定义队列缓冲池最大消息数,如果达到该值,那么队列检入将等待检出低于该值时继续进行. 3、定义检出线程,如果队列缓冲池没有消息,那么检出线程会线程等待中. if(size==0){ //队列缓存池没有消息,等待. if(isIpLock(queueStr)){//假若这个是一个多应用的分布式系统,那么这个判断应该是分布式锁,这里说的锁不是线程停止,而是跳过该消息,滞后处理.