消息队列总结(4)- RabbitMQ Kafka RocketMQ高性能方案
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。
- KafkaProducer发送消息后,会先经过分区器判断发往哪个双端队列。
- 找到具体的双端队列后,先判断ProducerBatch是否已满,若满了则创建一个新的ProducerBatch,否则追加到以后的ProducerBatch中。
接下来sender线程工作机制是:
- 寻找ReadyNode:sender到消息累加器中轮询存在哪些Node已经准备好的ProducerBatch,只要一个Node有任何一个ProducerBatch准备好,这个Node就会被认为是ReadyNode。
- 创建Request:拿到所有的ReadyNode,寻找其中准备好的ProducerBatch,对于一个Node下的ProducerBatch打包成一个Request,其中一个Request最多包含的ProducerBatch由max.request.size控制。
- 发起通讯:然后每个Request通过Selector发起通讯。
sender把消息发送到Broker有两个条件:
- 消息大小达到阈值(通常为1M,可以由message.max.bytes控制)
- 消息发送等待时间达到阈值(默认为60000ms,可以由max.block.ms控制)
2.2 消息持久化
磁盘通查查询一条数据的过程如下:
-
磁头寻道:磁盘驱动器中的读写磁头会移动到指定的磁道上。磁道是磁盘表面的一个环形轨道,用于存储数据。
-
磁道选择:一旦到达正确的磁道,磁头会选择正确的扇区。扇区是磁道上的一个小块,用于存储数据。
-
磁头等待:一旦选择了正确的扇区,磁头会等待磁盘旋转到正确的位置。这是为了确保磁头在正确的时间读取或写入数据。
-
数据读取/写入:一旦磁盘旋转到正确位置,磁头会读取或写入数据。数据通过磁场变化在磁盘表面上进行存储和读取。
从上面的过程可以看出,如果我们查询/写入一条数据是随机在磁盘的一个位置,那么整个过程会比较耗时。对于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博客
相关文章:

消息队列总结(4)- RabbitMQ Kafka RocketMQ高性能方案
1.RabbitMQ的高性能解决方案 1.1 发布确认机制 RabbitMQ提供了3种生产者发布确认的模式: 简单模式(Simple Mode):生产者发送消息后,等待服务器确认消息已经被接收。这种模式下,生产者发送消息后会阻塞&am…...

websocket服务端大报文发送连接自动断开分析
概述 当前springboot版本:2.7.4 使用依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dependency>现象概述: 客户端和服务端已经有心跳…...

想写几个上位机,是选择学c#还是 c++ qt呢?
C#基本也就上位机开发开发,另外做做日常用的小工具很方便。 结合PLC,以太网做上位机,这个基本上控制这块都比较有需求。 另外我们用C#也做一些工具的二次开发,感觉还行。 C用qt框架其实学习起来可能稍微复杂些,但是…...

JavaScript 简单实现观察者模式和发布-订阅模式
JavaScript 简单实现观察者模式和发布-订阅模式 1. 观察者模式1.1 什么是观察者模式1.2 代码实现 2. 发布-订阅模式2.1 什么是发布-订阅模式2.2 代码实现2.2.1 基础版2.2.2 取消订阅2.2.3 订阅一次 1. 观察者模式 1.1 什么是观察者模式 概念:观察者模式定义对象间…...

java集成短信服务 测试版 qq邮箱简单思路
java集成短信服务 注册一个帐号 使用的是容联云,百度搜一下官网 用手机注册一个帐号就行,免费体验不需要认证 注册后会有八块钱送,可以使用免费的给自己设置三个固定手机号发送短信,不需要认证。 此页面的 三个信息需要在代码中…...

#P0994. [NOIP2004普及组] 花生采摘
题目描述 鲁宾逊先生有一只宠物猴,名叫多多。这天,他们两个正沿着乡间小路散步,突然发现路边的告示牌上贴着一张小小的纸条:“欢迎免费品尝我种的花生!――熊字”。 鲁宾逊先生和多多都很开心,因为花生正…...

Elasticsearch和Kibana的安装及验证
金翅大鹏盖世英,展翅金鹏盖世雄。 穿云燕子锡今鸽,踏雪无痕花云平。 ---------------- 2023.7.31.101 ----------------- 本文密钥:365 Elasticsearch 是一个分布式的 RESTful 风格的搜索和数据分析引擎,常用来进行全文检索、…...

细讲TCP三次握手四次挥手(一)
计算机网络体系结构 在计算机网络的基本概念中,分层次的体系结构是最基本的。计算机网络体系结构的抽象概念较多,在学习时要多思考。这些概念对后面的学习很有帮助。 网络协议是什么? 在计算机网络要做到有条不紊地交换数据,就必…...
【linux-zabbix】zabbix-agent启动报错:Daemon never wrote its PID file. Failing.
背景: 发现有部分的agent失联,排查发现机器正常,agent没起来。 排查日志发现: # journalctl -xe -- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel -- -- Unit zabbix-agent.service has begun start…...
【微信小程序】初始化 wxCharts,调用updateData动态更新数据
要初始化 wxCharts,你需要按照以下步骤进行操作: 首先,确保已将 wx-charts.js 文件正确引入到小程序的相应页面或组件中。可以通过以下方式引入: const wxCharts require(../../../../components/wx-charts.js);请根据你的项目…...

【C语言初阶(19)】实用的 VS 调试技巧
文章目录 Ⅰ 调试的介绍Ⅱ 常用调试快捷键Ⅲ 调试的时候查看程序当前信息⒈查看临时变量的值⒉查看内存信息⒊查看调用堆栈⒋查看汇编信息⒌查看寄存器信息 Ⅳ 观察形参指针指向的数组Ⅴ 易于调试的代码该如何编写⒈const 修饰指针变量⒉良好代码示范 Ⅵ 编程中常见的错误 Ⅰ 调…...

虚拟机之间配置免密登录
目录 一、配置主机名映射 二、虚拟机配置SSH免密登录 三、验证 一、配置主机名映射 即修改/etc/hosts文件,将几台服务器和主机名进行映射。 注意每台服务器都要进行同样的配置。这样在各自服务器下,我们就可以通过主机名访问对应的ip地址了。 当然&…...

【contenteditable属性将元素改为可编辑状态】
元素添加contenteditable属性之后点击即可进入编辑状态 像这种只修改一条属性不必再打开弹框进行编辑,使用contenteditable会很方便 添加失焦、回车、获焦事件 如 <p :contenteditable"item.contenteditable || false"keydown.enter"key($event…...

Android 第三方库CalendarView
Android 第三方库CalendarView 根据需求和库的使用方式,自己弄了一个合适自己的日历,仅记录下,方便下次弄其他样式的日历。地址 需求: 只显示当月的数据 默认的月视图有矩形的线 选中的天数也要有选中的矩形框 今天的item需要…...

钉钉群消息推送
1. 添加钉钉群机器人 PC端登录(当前版本手机端无法进行推送关键词设置),群设置--> 机器人 --> webhook进行安全设置复制webhook对应的url 2. 群消息推送 钉钉群消息支持纯文本和markdown类型 2.1 调用示例源码 import com.alibaba.…...
css clip-path 属性介绍
circle() – 圆 语法:circle( [<shape-radius>]? [at <position>]? ) shape-radius 圆的半径 position 圆的中心点位置 使用方法: clip-path: circle(); // 以元素的中心点为圆的中心点,最小宽度一半为圆的半径。clip-path: c…...

Python之pyinstaller打包exe填坑总结
一、起因 编写了一个提取图片中文字的python脚本,想传给同事使用,但是同事电脑上没有任何python环境,更没有安装python库,因此想到通过pyinstaller打包成exe程序传给同事使用,于是开始了不断地挖坑填坑之旅 import p…...
Form Generator 表单JSON数据储存以及JSON回显表单
一、form-generator是什么?✨ ⭐️ 🌟 form-generator的作者是这样介绍的:Element UI表单设计及代码生成器,可将生成的代码直接运行在基于Element的vue项目中;也可导出JSON表单,使用配套的解析器将JSON解析成真实的表单。 但目前它提供的组件并不能满足我们在项目中的…...

Python - OpenCV识别条形码、二维码(已封装,拿来即用)
此代码可识别条形码和二维码,已封装好,拿来即用: import cv2 import pyzbar.pyzbar as pyzbar import numpy from PIL import Image, ImageDraw, ImageFontclass CodeScan():def __init__(self):super(CodeScan, self).__init__()def decode…...
Python如何快速实现爬取网页?
首先我们对要编写的爬虫程序进行简单地分析,该程序可分为以下三个部分: 拼接 url 地址发送请求将照片保存至本地 明确逻辑后,我们就可以正式编写爬虫程序了。 导入所需模块 本节内容使用 urllib 库来编写爬虫,下面导入程序所用…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...

最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...
Qt 事件处理中 return 的深入解析
Qt 事件处理中 return 的深入解析 在 Qt 事件处理中,return 语句的使用是另一个关键概念,它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别:不同层级的事件处理 方…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
TCP/IP 网络编程 | 服务端 客户端的封装
设计模式 文章目录 设计模式一、socket.h 接口(interface)二、socket.cpp 实现(implementation)三、server.cpp 使用封装(main 函数)四、client.cpp 使用封装(main 函数)五、退出方法…...