RocketMQ、Kafka、RabbitMQ 消费原理,顺序消费问题【图文理解】

B站视频地址



文章目录

  • 一、开始
  • 二、结果
    • 1、RocketMQ 消费关系图
      • 1-1、queue和consumer的关系
      • 1-2、consumer 和线程的关系
    • 2、Kafka 消费关系图
      • 1-1、partitions和consumer的关系
      • 1-2、consumer 和线程的关系
    • 3、RabbitMQ 消费关系图
      • 1-1、queue和consumer的关系
      • 1-2、consumer 和线程的关系
    • 4、总结
  • 三、实践
    • 1、全局有序
    • 2、局部有序


一、开始


先来定义一下何为顺序消息,比如有A、B两条消息,消息处理的流程是 1、2、3 … 10,只有当A消息执行10完毕后,B消息才可以进行1流程。

注:如果A执行到7,B开始执行1,这其实不一定是顺序消息,因为各种原因最终可能导致B先执行完10。


目前比较流行的队列:RocketMQ、RabbitMQ、Kafka

  • RocketMQ 消息发送到 topic,再到topic关联的 queue
  • RabbitMQ 消息发送到 exchange,再由exchange通过规则到 queue
  • Kafka 消息发送到 topic,再到topic关联的 partitions (partitions可以理解就是一个queue)

基于消息队列的规则,想要达到我们的目标就要求A、B两个消息先后发送到同一个 queue/partitions,且只能有一个消费者,且消费的时候必须是单线程非异步的才可满足。


二、结果


三种MQ都支持消息发送到指定的 queue/partition,简单来说就是基于一个标识去计算看它应该落在哪个queue/partition,同一批顺序消息的标识是一样的,所以最终进入的queue/partition也是一致的。 进入 queue/partition 之后的消息都是顺序的,它们是 FIFO的。

顺序消息的控制主要是在消费端,那问题就变成了2个

  1. queue/partition 和消费者之间是如何对应的
  2. 消费者对同一个 queue/partition 的消息,是多线程还是单线程

只有满足一个queue/partition 只能对应一个消费者,一个消费者对于一个queue/partition 是单线程消费的,才可以做到消费顺序。


注:MQ有集群消费和广播消费,顺序消费肯定是建立在集群消费模式下的。

最终结果:RocketMQ和Kafka是支持顺序消息的,RabbitMQ不支持顺序消息。


1、RocketMQ 消费关系图


1-1、queue和consumer的关系


在这里插入图片描述


从上面的图可以看到,一个queue最多只能对一个 consumer,如果某个 topic需要更大的并发,那就需要,那就增加 queue,然后增加 consumer


1-2、consumer 和线程的关系


正常使用SpringBoot开发项目的时候,都是引入 rocketmq-spring-boot-starter,然后用 @RocketMQMessageListener 来做消费处理,所以下面图也是基于这个用法来画的

在这里插入图片描述


通过这个图可以看到使用 @RocketMQMessageListener 做消费者的时候,本质上消息是被多线程去消费了,那就存在A、B消息的真正处理顺序不一致了。


RocketMQ的解决办法是,当你设置消费为顺序消费的时候,在消息处理的时候它会基于 queue加锁,这样就只能单线程处理这个queue的消息了。


设置顺序消费的代码

@RocketMQMessageListener(topic = "Topic1", consumerGroup = "springboot3_producer_group", consumeMode = ConsumeMode.ORDERLY
)

2、Kafka 消费关系图


Kafka 里面没有queue的概念,转而用partitions,但其本质上queue和partitions是一样的,就把它理解成一个queue完事


1-1、partitions和consumer的关系


partitions 和 consumer的关系和 RocketMQ的一模一样,只是把queue改为partitions即可,就不画了


1-2、consumer 和线程的关系


在这里插入图片描述


  1. Kafa消费消息的时候是主动去拉,拉到了就去消费,消费完了,再去拉。 拉和消费的线程是一个
  2. 当自定义线程数大于 partitions 的时候,没用,这个没用的意思是 Kafka压根不会创建比分配给自己 partitions 数量更多的线程
  3. 添加消费者的时候,会自平衡(这点所有的MQ都一样的)
  4. 默认如果没有给consumer设置线程数的话,是单线程

Kafka的解决办法是,每一个 partitions 最多只有一个线程来消费它,单线程自然就是顺序消费的咯。


3、RabbitMQ 消费关系图


1-1、queue和consumer的关系


在这里插入图片描述


  1. RabbitMQ新增了exchange(交换机)的概念,所有的数据都是先发送到交换机,再由exchange基于规则下发到具体的queue
  2. 可以通过设置交换机的类型的,让消息投递到一个或多个 queue
  3. 广播消息:可以设置exchange类型为fanout,这样消息就会投递到所有与之绑定的queue(前提是没有设置特殊的 routingkey)
  4. 集群消费:可以设置多个 consumer去消费一个queue,或一个消费者设置多线程去消费,以此来增加消费速率

注:RabbitMQ的queue和consumer是可以设置为多对多的关系


1-2、consumer 和线程的关系


在这里插入图片描述


  1. RabbitMQ默认也是一个线程消费
  2. 当开启了多个线程的时候,消息最终顺序就可能不一致,因为各个线程之间其实是相互独立的

4、总结


从上述结果来看其实三种队列都是支持顺序消息的(前提消息都发送到一个 queue/partitions),但支持的程度和结果不同

  1. RocketMQ,一个queue只能有一个consumer,消费者是多线程的,但开启顺序消费的时候,会对 queue加锁从而保证顺序
  2. Kafka,一个 partitions只能由一个consumer的一个线程去消费,基于单线程就保证了顺序性
  3. RabbitMQ,queue和consumer是多对多的,consumer的多个线程是独立的,要想保证顺序,只能让一个queue只有一个consumer,且consumer只有一个线程(但这样做效率就很低)

三、实践


1、全局有序


基于上述分析,三种MQ都可以做到全局有序,因为一旦要求全局有序,消费者就必须是单线程消费。


2、局部有序


比如用户订单业务,对于不同的用户它们的消费顺序可以不用关注,但是对于同一个用户的消息必须是严格有序的(简单的如先下单、再支付)。

对于这种场景RabbitMQ基本上就不满足的,它只有一个队列,如果消费者是单线程的会阻塞其它的消息,一定会造成消息积压。

RocketMQ和Kafka在发送消息的时候都可以指定一个queue/partitions(发消息的时候指定一个key,通过key的hash找一个queue,相同的key得到的就是同一个queue)。

  1. RocketMQ 通过顺序消息对queue加锁变成单线程消费
  2. Kafka 的每一个partitions 就只有一个线程去消费

消息可能重复消费这个和顺序消息没关系,所以在写消费逻辑的时候应该做幂等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/735763.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于美洲狮优化算法(Puma Optimizar Algorithm ,POA)的无人机三维路径规划(提供MATLAB代码)

一、无人机路径规划模型介绍 无人机三维路径规划是指在三维空间中为无人机规划一条合理的飞行路径,使其能够安全、高效地完成任务。路径规划是无人机自主飞行的关键技术之一,它可以通过算法和模型来确定无人机的航迹,以避开障碍物、优化飞行…

【牛客】VL68 同步FIFO

描述 请设计带有空满信号的同步FIFO,FIFO的深度和宽度可配置。双口RAM的参考代码和接口信号已给出,请在答案中添加并例化此部分代码。 电路的接口如下图所示。端口说明如下表。 接口电路图如下: 双口RAM端口说明: 端口名I/O描述…

docker容器的数据卷

1配置数据卷 docker run --namen01 -d --restartalways -p 80:80 -v /qy172/data/nginx/html:/usr/share/nginx/html nginx 2Docker应用部署 1搜索mysql镜像 docker search mysql 2拉取mysql镜像 docker pull mysql:5.6 3创建容器, 设置端口映射、目录映射 d…

GEE:基于ERA5数据集(U和V风速分量)计算风速的幅值和风向

作者:CSDN @ _养乐多_ 本文将介绍使用Google Earth Engine (GEE)平台提供的API加载ERA5月度数据集,该数据集包含了从1979年至今的全球月度气象数据。然后,定义了一个数据计算函数,用于将U和V风速分量转换为风速的幅值和风向。 结果如下图所示, 文章目录 一、核心函数1…

计算机设计大赛 行人重识别(person reid) - 机器视觉 深度学习 opencv python

文章目录 0 前言1 技术背景2 技术介绍3 重识别技术实现3.1 数据集3.2 Person REID3.2.1 算法原理3.2.2 算法流程图 4 实现效果5 部分代码6 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 深度学习行人重识别(person reid)系统 该项目…

力扣--76. 最小覆盖子串

给你一个字符串 s 、一个字符串 t 。返回 s 中涵盖 t 所有字符的最小子串。如果 s 中不存在涵盖 t 所有字符的子串,则返回空字符串 "" 。 注意: 对于 t 中重复字符,我们寻找的子字符串中该字符数量必须不少于 t 中该字符数量。如…

外边距折叠的原因和解决

参考文章 什么时候出现外边距塌陷 外边距塌陷,也叫外边距折叠,在普通文档流中,在垂直方向上的2个或多个相邻的块级元素(父子或者兄弟)外边距合并成一个外边距的现象,不过只有上下外边距才会有塌陷&#x…

有什么针对新闻媒体行业的安全解决方案

对媒体行业而言,门户网站是最易受到攻击的地方。常见的攻击方式有网页篡改、挂马和被植入暗链等。门户网站作为新闻媒体对外的第一扇门,通常承载了大量的流量,一旦遭到攻击,造成的影响会更具有可怕的“传播力”。那么我们应该如何…

搭建一款实用的个人IT工具箱——it-tools

一、it-tools介绍 IT-Tools是一款开源的个人工具箱,专为IT从业人员打造,支持Docker私有化部署,包含众多实用的IT工具。其功能丰富多样,涵盖二维码生成、数据格式转换、MAC地址生成等,可满足用户多样化的需求。 二、本…

开源的python代码分析工具介绍

本文将为您详细讲解开源的 Python 代码分析工具,以及它们的特点、区别和应用场景。Python 社区提供了多种代码分析工具,这些工具可以帮助您在 Python 应用程序中进行代码质量评估、性能分析、安全检查等功能。 1. Pylint 特点 - 用于检查 Python…

怎么在学习强国网上发布文章,学习强国投稿发稿方法途径,附学习强国多少钱价格明细表

学习强国是一款受用户欢迎的学习软件,许多人希望在其平台上发布自己的文章,以分享和传播自己的学习成果和心得体会。那么,怎么在学习强国网上发布文章呢?接下来,我们将介绍一些投稿发稿的方法和途径。 首先&#xff0c…

Feed、RSS、Atom概念对比及ROME实战

概述 在豆瓣等网站里,经常会看到如下订阅Button: 本文记录一下相关概念学习成果。 Feed Feed:消息来源,一种资料格式,网站通过它将最新资讯传播给用户。用户能够订阅某网站的前提条件是网站有提供Feed。Feed被很多…

方程式工具包远程溢出漏洞图形界面版V0.3(内置永恒之蓝、永恒冠军、永恒浪漫等)

Part1 前言 大家好,我是ABC_123。我从年前到现在,一直在整理曾经写过的红队工具,逐步把自己认为比较好用的原创工具发出来给大家用一用,方便大家在日常的攻防比赛、红队评估项目中解放双手,节省时间精力和体力。本期给…

Linux智能网关结合Node-RED实现实时工业数据采集

工业4.0的发展,物联网技术在制造业中的应用越来越广泛。其中,基于Linux系统的工业物联网智能网关因其开放性、稳定性和安全性而备受青睐。这类智能网关创新性地集成了开源工具Node-RED,为从各种工业设备(如PLC)中高效收…

LInux系统架构----Apache与Nginx动静分离

LInux系统架构----Apache与Nginx动静分离 一.动静分离概述 Nginx的静态处理能力比较强,但是动态处理能力不足,因此在企业中常采用动静分离技术在LNMP架构中,静态页面交给Nginx处理,动态页面交给PHP-FPM模块处理。在动静分离技术…

elementui的el-upload图片上传到服务器的对象储存cos并且展示出来

目录 0.前提1.准备工作1.买一个腾讯云服务器(你可以买其他的),我这里是去买了61元一年的轻量级应用云服务器,操场系统是宝塔Linux2.买一个对象储存cos(这里腾讯云可以不用购买,因为开通的时候可以有180天的…

单链表的基本操作--增删改查

增删改查 #include <stdio.h> #include <stdlib.h>#define OK 1 #define ERROR 0 typedef int Status; typedef char ElemType;typedef struct Lnode {ElemType data; //结点的数据域struct Lnode* next; //节点的指针域 }Lnode,*LinkList;初始化 Status InitLis…

【PCL】(二十八)超体素聚类分割点云

&#xff08;二十九&#xff09;超体素聚类分割点云 论文&#xff1a;Voxel Cloud Connectivity Segmentation - Supervoxels for Point Clouds supervoxel_clustering.cpp #include <pcl/console/parse.h> #include <pcl/point_cloud.h> #include <pcl/poin…

重启 explorer 进程的正确做法(二)

重启资源管理器进程的方法不唯一&#xff0c;但长期以来大家对实施方法用的不到位。 在上一篇中我认为&#xff1a;“我们往往使用 TerminateProcess 并传入 PID 和特殊结束代码 1 或者 taskkill /f /im 等方法重启资源管理器( explorer.exe )&#xff0c;其实这是不正确的。我…

21 卷积层里的多输入多输出通道【李沐动手学深度学习v2课程笔记】

目录 1. 多输入输出通道&相应代码实现 1.1 多输入 1.2 多输出 1.3 1x1 卷积层 1.4 小结 1. 多输入输出通道&相应代码实现 1.1 多输入 为了加深理解&#xff0c;我们实现一下多输入通道互相关运算。 简而言之&#xff0c;我们所做的就是对每个通道执行互相关操作&a…