首页 > 其他分享 >消息队列三兄弟谁主沉浮

消息队列三兄弟谁主沉浮

时间:2023-07-04 21:44:20浏览次数:44  
标签:存储 主沉浮 队列 broker Kafka topic 兄弟 消息

简介

消息队列主要为了异步场景下实现上下游解耦功能:在传统场景中,上游产生一条消息,比如用户下单了一件商品,系统创建了对应的订单,需要通知下游的物流、支付等系统进行后续处理;消息队列可以使得上游系统(订单)和下游系统(支付/物流等)解耦,上游只管向消息队列中投递消息即可,下游订阅消息并做相关处理,这使得系统具有极大的可扩展和伸缩性 -- 扩展新系统、上下游利用消息队列做缓冲实现“削峰填谷”等。

目前生产环境主流的开源MQ产品有RabbitMQ、Kafka、RocketMQ,今天分析下它们的异同:

背景

RabbitMQ使用Erlang语言写的,由Rabbit公司创建,后被VMware公司收购,是老牌MQ的代表。

Kafka使用Scala和Java编写,最初由领英公司开发,后捐献给Apache基金会,目标是为处理实时数据提供一个统一、高吞吐、低延迟的平台

RocketMQ使用Java语言编写,由阿里巴巴公司开发,在Kafka基础上结合阿里内部电商场景自研设计,2012年开源,并于16年捐献给Apache基金会,17年成为Apache基金会顶级项目。在国内软件开发领域,尤其是在线业务和电商物流等场景下,RocketMQ非常流行(有意思的一点是,在国外RocketMQ远没有RabbitMQ热门,相关英文文档都较少)

MQ模型

RabbitMQ实现了AMQP协议,并支持点对点和发布订阅模式,支持同步通信或异步通信;

Kafka仅支持发布订阅模式,适用于实时流式任务处理,支持高并发,是日志传输、大数据分析场景中的常见选型

RocketMQ仅支持发布订阅模式,适用于在线业务场景,可靠性高,并发能力强,还支持一些事务、定时、延迟消息等高级特性。

MQ架构

RabbitMQ中的核心是queue,queue负责存储、分发消息;生产者通过exchange向queue发送消息,exchange承担消息路由的角色,消费者连接到队列并取消息进行处理。这种架构模式使得RabbitMQ具备发布订阅、topic分发、同步RPC调用等通信模型。详情可看
www.rabbitmq.com/getstarted.…

 

broker在Kafka中是实际的物理服务,多台broker构成Kafka集群。Kafka中的核心是topic,topic是一个逻辑概念,对于实际用户使用/编程角度来讲,只需感知到topic层即可,topic实际是由物理层的partition组成。partition按照leader-follower的架构分布在broker上,消费者实际是跟partition打交道的,这里的partition类似RabbitMQ中的queue。详情可看 www.modb.pro/db/585123

 

RocketMQ的架构和Kafka非常类似,只不过将partition的概念替换成了message queue,且去掉了leader-follower架构,由实际的broker的master-slave来保证高可用。详情可看
rocketmq.apache.org/zh/docs/dom…

 

存储架构

RabbitMQ存储结构包含如下部分:

  • index: rabbit_queue_index 负责维护队列中落盘消息的信息,包括消息的存储地点、是否已被交付给消费者、是否已被消费者 ack 等。每个队列都有与之对应的一个 rabbit_queue_index
  • store: rabbit_msg_store 以键值对的形式存储消息,它被所有队列共享,在每个节点中有且只有一个

详情大家可以去这里了解下
www.cnblogs.com/wujuntian/p…

Kafka的消息存储以partition为单位;而partition又由多个segment构成,相当于一种分片机制。segment的底层的存储由index和log文件构成,index存储每个消息的offset索引,log文件存储实际的消息内容。详情可见
www.cnblogs.com/rickiyang/p…

 

Kafka的partition由一个leader和多个follower构成高可用系统,所有的读写请求都落到leader上,follower负责同步leader上的消息存储以及在故障等场景下重新选主。

RocketMQ的消息存储主要由四部分构成:

  • commitlog:消息元信息和消息内容的存储文件。单个文件最大为1GiB。以起始消息的偏移字节数命名文件,第一个文件名是00000000000000000000,第二个是00000000001073741824(1073741824 = 102410241024),后续文件依次类推。同一台broker的所有topic消息都统一存储在commitlog文件中。
  • consumequeue:单个broker上的所有topic信息都存储在commitlog文件中,这样消费者查询起来需要重新检索文件,效率低性能差;consumequeue文件按照topic+queueid目录结构组织,单个consumequeue由30w条记录组成,每条记录包含每条消息在commitlog中的偏移量、消息长度和tag hashcode,共计20字节(8+4+8),所以单个consumequeue的大小有约5.4MiB
  • indexfile:IndexFile(索引文件)提供了一种可以通过key或时间区间来查询消息的方法。文件名fileName是以创建时的时间戳命名的,固定的单个IndexFile文件大小约为400M,一个IndexFile可以保存 2000W个索引,IndexFile的底层存储设计为在文件系统中实现HashMap结构,故rocketmq的索引文件其底层实现为hash索引。
  • offset:offset用来管理每个消费队列的不同消费组的消费进度。对offset的管理分为本地模式和远程模式,本地模式是以文本文件的形式存储在客户端,而远程模式是将数据保存到broker端,对应的数据结构分别为LocalFileOffsetStore和RemoteBrokerOffsetStore。默认情况下,当消费模式为广播模式时,offset使用本地模式存储,因为每条消息会被所有的消费者消费,每个消费者管理自己的消费进度,各个消费者之间不存在消费进度的交集;当消费模式为集群消费时,则使用远程模式管理offset,消息会被多个消费者消费,不同的是每个消费者只负责消费其中部分消费队列,添加或删除消费者,都会使负载发生变动,容易造成消费进度冲突,因此需要集中管理。同时,RocketMQ也提供接口供用户自己实现offset管理(实现OffsetStore接口)。远程模式存储位置见config/consumerOffset.json

上述四部分的存储文件在broker上的位置如下所示:

 

性能表现

RabbitMQ单机一般可以达到几万吞吐量。

单个Kafka集群一个topic的吞吐能力号称可以达到百万TPS。得益于Kafka的分区机制和消息批量发送机制。不同分区间的消息发送和消费是完全独立的,但是过多的分区因单机磁盘IO竞争会造成单机吞吐能力下降,所以一般药控制单个broker的partition数目,一种说法是单机超过64个分区后写入性能严重下降。

单个Rocket集群一个topic的吞吐能力一般可以达到几十万TPS。因为单个broker的所有topic都是写入到同一个commitlog文件,所以topic&队列数量的上升并不会非常影响性能,单broker一般可以支持5w队列。

选型

那在实际的业务场景中,该如何去选择合适的MQ类型呢?其实没有非常绝对的优劣,通常大部分业务场景下任意选一种影响都不是很大,但是通常会有以下的偏爱:

  • 国内的JAVA用户更加倾向于RocketMQ和Kafka,因为这两都是由java写的。
  • 一般Kafka更适合大数据、日志传输等离线场景,因为Kafka的吞吐性能要优于其他两者
  • RocketMQ更适合在线业务场景,因为它具有较高稳定性,另外还有很多的高级特效:如消息重试、延迟、定时消息,这是从阿里实际场景中孵化出来的产品,相关业务场景可以优先选择
  • RabbitMQ是个老牌的MQ产品,这两年好像渐渐被前两者所掩盖。但是它是非常标准的AMQP协议实现,有非常丰富的消息中间件的功能,可以作为学习研究对象。

总而言之,每个MQ产品都是有可取之处,如何利用好它并解决实际的业务场景,这才是最关键的!

标签:存储,主沉浮,队列,broker,Kafka,topic,兄弟,消息
From: https://www.cnblogs.com/nifrecxgh/p/17527102.html

相关文章

  • 单调栈单调队列学习笔记
    目录:单调栈1.1概念1.2实现1.3时间复杂度分析1.4应用单调队列1.1概念1.2实现1.3时间复杂度分析1.4应用习题1.单调栈1.1概念单调栈为满足单调性的栈结构,栈内元素满足单调性。1.2实现为满足单调性,在遍历到一个元素时,若此时加入后栈不满足单调性,则弹出栈......
  • 单调栈与单调队列
    单调栈数组/栈中的数满足单调性质(递增或递减),可查询\(1-i\)中的最小值或是最大值。实现:(以单调上升举例)将数按顺序压入栈中,若新压入的数小于前一个数(不满足单调性),则弹出前一个数,继续向前比较,直至满足大于前一个数(满足单调性)时将此数入队。代码:while(s[now]<a[i]){//不满......
  • c++实现多线程消息通信队列
    #ifndef_SYNC_SIMPLEQUEUE_QUEUE_HPP_#define_SYNC_SIMPLEQUEUE_QUEUE_HPP_#include<queue>usingnamespacestd;namespaceutility{template<typenameT>classSyncSimpleQueue{public:voidput(constT&msg){std::uniqu......
  • UVA210 双端队列模拟并行程序
    #include<iostream>#include<algorithm>#include<string>#include<sstream>#include<vector>#include<queue>#include<cstring>usingnamespacestd;constintmaxn=10001;//uva210:题意模拟n个程序的并行执行,有赋值,打印,lock,unlock,......
  • 【牛客小白75】D 矩阵 【bfs+优先队列】
    题目https://ac.nowcoder.com/acm/contest/60063/D题意是说,给你一张\(n*m(n,m\leq10^3)\)大小的01地图,当前点下一步只能走到相邻的点上,如果这两个点值相同,则代价为2,否则代价为1,问从(1,1)走到(n,m)最少代价是多少思路首先很容易想到只往右下走是错的,有可能往左和往上走总代价更......
  • js 数组和链表分别实现队列
    链表实现/***1.单项链表实现队列,但要同时记录head和tail*2.要从tail入队,head出对,否则出队时,tail不好定位*2.单独记录length,不可遍历链表获取length*/classMyQueue{head=null;//头tail=null;//尾len=0;add(n){letnewNode={......
  • 单调队列
    目录单调队列例题洛谷P18862023暑假训练-单调队列单调栈单调队列单调的队列,即插入元素时保证队列是单调的。去尾、删头、窗口来维护一个单调队列例题洛谷:P2629洛谷P1886代码:constintmaxm=1e6+5,inf=0x3f3f3f3f,mod=998244353;lln,k,a[maxm];deque<ll>q;//单调队列......
  • 2023ACM暑假训练day 5-单调队列 单调栈
    目录DAY5单调队列/栈训练情况简介A题B题C题D题E题未出,题解补F题未出,题解补G题看了cf数据,得wa启发补充内容单调栈MonotoneStack单调栈矩形系列字典序最小贡献法单调队列MonotoneQueueDAY5单调队列/栈训练地址:传送门训练情况简介早上:A、B、C、D题下午:E题(未......
  • IBM WebSphere MQ8.0 安装与队列创建
    最近接触的项目中使用了IBMWebsphereMQ8.x,由于要为其编写监控插件,所以在网上找了很久的资料,发现8.x实在是太老了,很多资源和教程都没有,遂决定在此统一整理和记录一下.安装下载安装包IBM官方已不再提供下载,这里贴一下网盘的链接链接:https://pan.baidu.com/s/1f2U0XqEe0hi......
  • 最近有很多兄弟萌跟我反应“无法安装此app,因为无法验证其完整性
    最近有很多兄弟萌跟我反应“无法安装此app,因为无法验证其完整性”,看来这个问题无法避免了,今天统一回复下,出现提示主要有以下几种可能 1.安装包不完整首先申请我所有分享的破解软件全部都有自己校验过,一般不会存在问题出非你手机版本跟我相差较大,所以不可能存在什么应用不完......