消息队列总结(4)- RabbitMQ Kafka RocketMQ高性能方案

news2024/11/16 21:59:21

1.RabbitMQ的高性能解决方案

1.1 发布确认机制

RabbitMQ提供了3种生产者发布确认的模式:

  • 简单模式(Simple Mode):生产者发送消息后,等待服务器确认消息已经被接收。这种模式下,生产者发送消息后会阻塞,直到收到服务器确认消息。如果服务器在确认消息前崩溃,生产者会重新发送消息。​ 同步等待确认,实现简单,但是吞吐量十分有限

  • 批量模式(Batch Mode):生产者发送一批消息后,等待服务器一次性确认这批消息已经被接收。这种模式相比简单模式有更高的吞吐量,因为确认是批量进行的。批量同步等待确认,实现简单,吞吐量较大,但是很难找出未确认的消息,其中一个失败后需要把一个批次都重试。

  • 异步模式(Asynchronous Mode):生产者发送消息后,不会等待服务器的确认消息。而是通过回调函数来处理确认和错误信息。这种模式适用于对消息可靠性要求不高的场景,可以提高生产者的性能。​ 可靠性和性能最好,在出现未确认消息时容易处理,但是实现困难。

1.2 预取机制

RabbitMQ的默认分发方式是轮询分发,轮询分发的问题是会导致消费快的消费者空闲,消费慢的消费者一直干活。为了解决这个问题,RabbitMQ引入了不公平分发机制,可以把任务分发给空闲的消费者。

Channel channel = connection.createChannel();
channel.basicQos(1)

上面案例中方法basicQos的参数PrefetchCount(案例中等于1)是最大传输信息数,当消息由消费者消费完成之后,再次从Queue中获取消息,达到预取值。

  • PrefetchCount = 0:轮询分发
  • PrefetchCount = 1:不公平分发
  • PrefetchCount > 1:设置不公平分发,并设置预期值

通过预取值的机制可以减少消费者与磁盘之间的交换次数,从而提升消费者的处理能力。

2. Kafka的高性能解决方案

2.1 批量发送

 Producer会为每个Partition创建一个双端队列来缓存客户端的消息,队列中的每个元素是PorducerBatch,PorducerBatch的每个元素就是客户端要发送的Msg。

  1. KafkaProducer发送消息后,会先经过分区器判断发往哪个双端队列。
  2. 找到具体的双端队列后,先判断ProducerBatch是否已满,若满了则创建一个新的ProducerBatch,否则追加到以后的ProducerBatch中。

接下来sender线程工作机制是:

  1. 寻找ReadyNode:sender到消息累加器中轮询存在哪些Node已经准备好的ProducerBatch,只要一个Node有任何一个ProducerBatch准备好,这个Node就会被认为是ReadyNode。
  2. 创建Request:拿到所有的ReadyNode,寻找其中准备好的ProducerBatch,对于一个Node下的ProducerBatch打包成一个Request,其中一个Request最多包含的ProducerBatch由max.request.size控制。
  3. 发起通讯:然后每个Request通过Selector发起通讯。

sender把消息发送到Broker有两个条件:

  • 消息大小达到阈值(通常为1M,可以由message.max.bytes控制)
  • 消息发送等待时间达到阈值(默认为60000ms,可以由max.block.ms控制)

2.2 消息持久化

磁盘通查查询一条数据的过程如下:

  1. 磁头寻道:磁盘驱动器中的读写磁头会移动到指定的磁道上。磁道是磁盘表面的一个环形轨道,用于存储数据。

  2. 磁道选择:一旦到达正确的磁道,磁头会选择正确的扇区。扇区是磁道上的一个小块,用于存储数据。

  3. 磁头等待:一旦选择了正确的扇区,磁头会等待磁盘旋转到正确的位置。这是为了确保磁头在正确的时间读取或写入数据。

  4. 数据读取/写入:一旦磁盘旋转到正确位置,磁头会读取或写入数据。数据通过磁场变化在磁盘表面上进行存储和读取。

从上面的过程可以看出,如果我们查询/写入一条数据是随机在磁盘的一个位置,那么整个过程会比较耗时。对于Kafka来说,采用的策略是使用顺序IO,这样就可以避免寻址的过程,直接操作对数据的读/写操作。

2.3 零拷贝

 

 传统情况下,从磁盘读取数据,并通过网络发出去需要2次CPU copy和2次DMA copy:

  • 数据读取过程:DMA执行了一次数据拷贝,数据从磁盘拷贝到内核空间。cpu再将数据从内核空间拷贝到用户空间(用户缓冲区)。

  • 数据发送过程:cpu发生第三次数据拷贝,由cpu将数据从用户空间拷贝至内核空间(socket缓冲区),DMA执行第四次数据拷贝,将数据从内核空间写到网卡。

Linux2.4+的Linux系统支持了sendfile + DMA Gather

  • 发起一次sendfile()系统调用,进行一次上下文切换,数据从磁盘DMA copy到内核缓冲区。
  • 将内核缓冲区中带有文件位置、文件信息的缓冲区描述符copy到Socket缓冲区,然后借助DMA Gather真正的数据直接DMA copy到网卡。

这样只有两次上下文切换和两次DMA copy极大的减少了系统开支。 

3.RocketMQ的高性能解决方案

3.1 异步机制

RocketMQ在高性能上与Kafka类似,使用异步、批量、零拷贝的机制,来实现高吞吐量。具体RocketMQ的异步机制如下:

  • 数据写入CommitLog:Broker接收来自Producer发出的消息,获取CommitLog最新offset,并往CommitLog对应ByteBuffer追加数据。
  • 异步写磁盘:Broker通过同步/异步的方式写入到磁盘。若为异步写入磁盘,则是把数据写入OS的Page Cache就给Producer返回ACK,后台线程异步把Page Cache的数据写的磁盘。
  • 异步复制:Broker通过同步/异步的方式进行Master/Slave之间的数据同步。若为异步复制,则是数据写入Master成功即视为成功,再后台异步同步至其他Slave。
  • 异步写ConsumerQueue:后台线程轮询CommitLog的offset是否发生变化,若发生变化,则计算CommitLog对应消息的commitLog Offset、size、Message Tag HashCode写入ConsumerQueue。
  • 异步写IndexFIle:写入ConsumerQueue后,再将消息Key Hash、commitLog Offset、TimeStamp、Next Index Offset写入到到IndexFile。

(在RocketMQ中使用的批量发送、零拷贝等机制在上面已讲过,不再重复陈述)

4. 参考文档

Kafka由浅入深(6) Sender线程执行源码解析_kafka sender源码解析_架构源启的博客-CSDN博客

Kafka全面学习_kafka学习_oraen的博客-CSDN博客

零拷贝技术----sendfile_socket 零拷贝_不吃树叶的树袋熊的博客-CSDN博客

kafka-生产者源码解析_kafka request.timeout.ms_SnaiI的博客-CSDN博客

RocketMQ源码分析之消息写入_rocketmq 写入 json数据_不爱学习的小妞的博客-CSDN博客

RocketMQ源码解读四 Broker写入数据_python 从mq写入文件_colspanprince的博客-CSDN博客

Java 两种zero-copy零拷贝技术mmap和sendfile的介绍_sendfile和mmap的比较_刘Java的博客-CSDN博客

多图详解 kafka 生产者消息发送过程_kafka生产者发送消息_Java程序V的博客-CSDN博客

Rabbitmq消息队列详解_rabbitmq查看消息队列_☜阳光的博客-CSDN博客

【RabbitMQ】Producer之publisher confirm、transaction - 基于AMQP 0-9-1_穿越在未来的博客-CSDN博客

spring-rabbit消费过程解析及AcknowledgeMode选择_acknowledge-mode_JinchaoLv的博客-CSDN博客

RabbitMQ持久化机制_琦彦的博客-CSDN博客

rabbitmq基础8——持久化、存储机制、ETS、队列结构、消息状态、内存告警、磁盘告警_rabbitmq存储机制_百慕卿君的博客-CSDN博客

从数据存储分析RocketMQ的高性能设计_rocketmq性能_怪兽靠边闪的博客-CSDN博客

RabbitMQ、RocketMQ和Kafka之间有什么性能差距?_mq性能对比_Java技术攻略的博客-CSDN博客

计算机操作系统(二十二):磁盘_操作系统 磁盘转速 扇区_BKSW.的博客-CSDN博客

零拷贝技术:mmap和sendfile_零拷贝mmap和sendfile_johnny233的博客-CSDN博客

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

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

相关文章

M5ATOMS3基础03给ROS1发一个问候(rosserial)

引出问题 关于之前2020年的博客: 01. ESP8266和ROS调试一些问题汇总 02. ESP8266和ESP32配置(需使用ROS1和ROS2) 效果展示 使用M5ATOMS3与ROS1(kinetic,melodic,noetic)版本通信比较通用的是…

BUU [网鼎杯 2020 朱雀组]phpweb

BUU [网鼎杯 2020 朱雀组]phpweb 众生皆懒狗。打开题目,只有一个报错,不知何从下手。 翻译一下报错,data()函数:,还是没有头绪,中国有句古话说的好“遇事不决抓个包” 抓个包果然有东西,仔细一看这不就分别是函数和参…

【算法基础:贪心】6. 贪心

文章目录 区间问题905. 区间选点(排序 贪心)908. 最大不相交区间数量(排序 贪心)906. 区间分组(排序 优先队列 贪心)⭐907. 区间覆盖(排序 贪心) Huffman树148. 合并果子&#…

【LeetCode 75】第十四题(643)子数组最大平均数

题目: 示例: 分析: 给一个数组,问数组里长度为k的连续数组中的最大平均值是多少. 这题已经把意思说的很明白了,并且连子数组的长度都固定了,并且是连续的,这里可以直接使用固定长度的滑动窗口来计算. 用两个指针来在数组里划定一个长度为k的范围,然后计算指针范围内的平均数…

数组传参,指针传参

文章目录 一维数组传参二维数组传参一级指针传参二级指针传参 一维数组传参 二维数组传参 一级指针传参 二级指针传参

CentOS 8 上安装 Nginx

Nginx是一款高性能的开源Web服务器和反向代理服务器,以其轻量级和高效能而广受欢迎。在本教程中,我们将学习在 CentOS 8 操作系统上安装和配置 Nginx。 步骤 1:更新系统 在安装任何软件之前,让我们先更新系统的软件包列表和已安…

【树链剖分+MST】CF609E

Problem - E - Codeforces 题意: 思路: 先把全局的MST求出来,然后对于一条边,如果它本来就在MST中,说明代价就是MST的权值和,否则它加入MST中,此时MST形成了环,我们把环中最大的那…

深入探究Java面向对象的三大特征:封装、继承、多态

文章目录 1. 封装(Encapsulation)2. 继承(Inheritance)3. 多态(Polymorphism)结语 导语:Java是一门面向对象的编程语言,其核心思想是将现实世界中的事物抽象成对象,并通过…

Python(五十二)列表元素的判断及遍历

❤️ 专栏简介:本专栏记录了我个人从零开始学习Python编程的过程。在这个专栏中,我将分享我在学习Python的过程中的学习笔记、学习路线以及各个知识点。 ☀️ 专栏适用人群 :本专栏适用于希望学习Python编程的初学者和有一定编程基础的人。无…

自己整理的JAVA集合

概括: 数组,链表,散列表,二分查找树,红黑树是五种不同的数据结构,它们有各自的特点和用途。ArrayList,LinkedList,HashTable,LinkedHashMap,HashMap 是 Java…

Camera组件

Clear Flags: Skybox:天空盒 Solid Color:填充颜色,当有空白处时填充背景颜色 Depth Only:只渲染想要渲染的层级 Dont Clear:不清除上一帧所留下来的数据,可以做类似残影的效果 Culling Mas…

Unity Addressable

Unity重要目录 工程中的几个重要目录 Assets存放资源、代码、配置Library大部分的资源导入到Assets目录之后,会转化成Unity认可的文件,转化后的文件会存储在这个目录Logs日志文件Packages第三方插件ProjectSettings存放各种项目设定UserSettings用户偏好…

CentOS 8 错误: Error setting up base repository

配置ip、掩码、网关、DNS VMware网关可通过如下查看 打开网络连接 配置镜像的地址 vault.centos.org/8.5.2111/BaseOS/x86_64/os/

java 阿里云 发送短信功能实现

1. 注册短信平台(以阿里云为例) 常用短信服务平台:阿里云、华为云、腾讯云、京东、梦网、乐信等 2. 注册成功后,开通短信服务 3. 设置短信签名、短信模板、AccessKey AccessKey 是访问阿里云 API 的密钥,具有账户的完全权限,我们…

C语言实现三子棋游戏

test.c源文件 - 三子棋游戏测试 game.h头文件 - 三子棋游戏函数的声明 game.c源文件 - 三子棋游戏函数的实现 主函数源文件: #define _CRT_SECURE_NO_WARNINGS 1#include"game.h" //自己定义的用"" void menu() {printf("*************…

代码随想录算法训练营day43

文章目录 Day43 最后一块石头的重量II题目思路代码 目标和题目思路代码 一和零题目思路代码 Day43 最后一块石头的重量II 1049. 最后一块石头的重量 II - 力扣(LeetCode) 题目 有一堆石头,每块石头的重量都是正整数。 每一回合&#xff0…

2023-07-30 LeetCode每日一题(环形链表 II)

2023-07-30每日一题 一、题目编号 142. 环形链表 II二、题目链接 点击跳转到题目位置 三、题目描述 给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。 如果链表中有某个节点,可以通过连续跟踪 n…

【探索C++中的顺序表】手动实现vector容器

🚀write in front🚀 📜所属专栏:初阶数据结构 🛰️博客主页:睿睿的博客主页 🛰️代码仓库:🎉VS2022_C语言仓库 🎡您的点赞、关注、收藏、评论,是对…

Fourier变换及其应用(Brad G. Osgood)——第2章——Fourier变换

第2章 Fourier变换 2.1 初识Fourier变换(A First Look at the Fourier Transform) 我们即将从Fourier级数过渡到Fourier变换。“过渡(transition)”是合适的词,因为我们选择了Fourier变换从周期函数到非周期函数的引出路径。 为了完成这一旅程,我们将把…

【优选算法题练习】day10

文章目录 一、137. 只出现一次的数字 II1.题目简介2.解题思路3.代码4.运行结果 二、剑指 Offer 53 - II. 0~n-1中缺失的数字1.题目简介2.解题思路3.代码4.运行结果 三、153. 寻找旋转排序数组中的最小值1.题目简介2.解题思路3.代码4.运行结果 总结 一、137. 只出现一…