【RocketMQ】(八)Rebalance负载均衡

消费者负载均衡,是指为消费组下的每个消费者分配订阅主题下的消费队列,分配了消费队列消费者就可以知道去消费哪个消费队列上面的消息,这里针对集群模式,因为广播模式,所有的消息队列可以被消费组下的每个消费者消费不涉及负载均衡,而集群模式一个消息队列同一时间只能分配给组内的一个消费者进行消费。

RocketMQ 5.0以前是按照队列粒度进行负载均衡的,5.0以后提供了按消息粒度进行负载均衡。

队列粒度负载均衡

对于4.x/3.x的版本,包括DefaultPushConsumer、DefaultPullConsumer、LitePullConsumer等,默认且仅能使用队列粒度负载均衡策略。
队列粒度负载均衡策略中,同一消费者组内的多个消费者将按照队列粒度消费消息,每个队列只能被其中一个消费者消费。

注:图片来自RocketMQ官方文档

队列粒度负载均衡是在每个消费者端进行的,并不是由某个节点统一进行负载均衡之后将分配结果通知到每个消费者。消费者增加或者减少会影响消息队列的分配,所以Broker需要感知消费者的上下线情况,消费者在启动时会向所有的Broker发送心跳包进行注册,通知Broker消费者上线,下线的时候也会向Broker发送取消注册的请求,Broker会维护消费者信息的注册信息,在消费者发生变更时会通知消费者进行负载均衡。

Rebalance过程

消费者在启动的时候,会立刻触发一次负载均衡,为消费者分配消息队列。为了保证消费者拿到的主题路由信息是最新的(topic下有几个消息队列、消息队列的分布信息等),消费者会向NameServer发送请求,更新每一个主题的路由信息,保证路由信息是最新的。

  1. 根据Topic获取该Topic下的所有消费队列(MessageQueue对象), 消费者在启动时已经向NameServer发送请求获取了最新Topic的路由信息,里面可以获取到Topic下的所有消费队列;

  2. 由于负载均衡是在每个消费者端进行的,负载均衡时还需要知道订阅该主题的消费者组下都有哪些消费者,这个数据可以通过Broker获取,通过向Broker发送请求,查找订阅了该主题的所有消费者的ID(消费者会向Broker注册,所以可以通过Broker查找订阅了某个Topic的消费者);

  3. 如果主题对应的消息队列集合和获取到的消费者ID都不为空,对消息队列集合和消费ID集合进行排序;

  4. 获取分配策略,根据具体的分配策略,为当前的消费者分配对应的消费队列,RocketMQ默认提供了以下几种分配策略:

    • AllocateMessageQueueAveragely:平均分配策略,根据消息队列的数量和消费者的个数计算每个消费者分配的队列个数。
    • AllocateMessageQueueAveragelyByCircle:平均轮询分配策略,将消息队列逐个分发给每个消费者。
    • AllocateMessageQueueConsistentHash:根据一致性 hash进行分配。
    • AllocateMessageQueueByConfig:根据配置,为每一个消费者配置固定的消息队列 。
    • AllocateMessageQueueByMachineRoom:分配指定机房下的消息队列给消费者。
    • AllocateMachineRoomNearby:优先分配给同机房的消费者。
  5. 根据最新分配的消息队列,更新当前消费者负责的消息处理队列;

    由于负载均衡之后,消费者负责的消息队列可能发生变化,所以这里需要更新当前消费者负责的消息队列,之后就可以拉取消息进行消费了。

Rebalance的触发时机

一、消费者启动时触发
消费者在启动时会进行一次负载均衡,为自己分配消息队列。

二、Broker发现消费组变更时触发
处于以下两种情况之一时会被判断为消费组发生了变化,需要进行负载均衡:

(1)某个消费组内有新的消费者向Broker进行了注册,比如某个消费组原来有两个消费者,现在新增了一个消费者,新增的消费者启动时会向Broker发送注册请求;

(2)消费组订阅的主题信息发生了变化,比如消费组新增订阅了某个主题或者取消某个主题的订阅,会被判断为主题订阅信息发生了变化;

被判定为变化之后,会触发变更事件,向该消费者下的所有消费者发送发送变更请求,通知组下每个消费者进行负载均衡。

三、Broker收到消费者下线时触发
如果有消费者向Broker发送UNREGISTER_CLIENT取消注册请求,并且开启了允许通知变更,会触发变更事件,变更事件同上,Broker会通知该消费者组下的所有消费者进行一次负载均衡。

四、消费者定时触发
消费者本身也会定时执行负载均衡,默认是20s执行一次;

负载均衡源码解析可参考:【RocketMQ】【源码】负载均衡源码分析

特点

缺点
(1)队列粒度负载均衡策略分配粒度较大,不够灵活;
(2)队列粒度负载均衡策略保证同一个队列仅被一个消费者处理,在消费者数量、队列数量发生变化时,可能会出现短暂的队列分配结果不一致,从而导致少量消息被重复处理。
(3)如果队列数量和消费者数量不均衡,可能会出现部分消费者空闲或者部分消费者分配到的消息队列过多的情况。

优点
在流式处理场景下有优势,能够保证同一队列的消息被相同的消费者处理,对于批量处理、聚合处理更友好。

消息粒度负载均衡

在RocketMQ 5.0之后,增加了消息粒度负载均衡策略,对于PushConsumer和SimpleConsumer类型的消费者,默认且仅使用消息粒度负载均衡策略。

消息粒度负载均衡策略中,同一消费组内的多个消费者将按照消息粒度平均分摊主题中的所有消息,即同一个队列中的消息,可被平均分配给组内多个消费者共同消费。

注:图片来自RocketMQ官方文档

消息粒度负载均衡策略保证同一个队列的消息可以被组内多个消费者共同处理,但是该策略使用的消息分配算法结果是随机的,不能指定消息被哪一个特定的消费者处理。当消费者获取到某条消息后,服务端会对该消息加锁,保证该消息对其他消费者不可见,直到消息消费成功或者超时,所以多个消费者同时消费同一个消息队列中的消息,服务端也可以保证消息不会被多个消费者重复消费。

特点

(1)**消费分摊均衡可以更均匀的分摊消息:**不会像队列粒度负载均衡一样,出现分配不平衡的情况。
(2)对非对等消费者更友好:如果网络机房延迟、消费者物理资源规格不一致等原因,按照队列分配消息,可能出现部分消费者堆积、部分消费者空闲的情况,本质还是分摊更均匀。
(3)队列分配运维更方便:队列粒度负载均衡需要保证队列数量大于等于消费者数量,以免某些消费者获取不到队列出现空闲的情况,消息粒度负载均衡无需关注队列的数量。

消息粒度负载均衡策略适用于绝大多数在线处理的业务场景,对于流式处理、聚合计算等场景,更适合队列粒度的负载均衡策略。

参考
RocketMQ官方文档

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

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

相关文章

【Linux】线程概念

🔥🔥 欢迎来到小林的博客!!       🛰️博客主页:✈️林 子       🛰️博客专栏:✈️ Linux       🛰️社区 :✈️ 进步学堂       &#x1f6f0…

[VIM]VIM初步学习-3

3-1 编写 vim 配置,我的 vim 我做主_哔哩哔哩_bilibili

C# DeOldify 黑白照片 老照片上色

效果 项目 代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System…

NPDP产品经理知识(市场调研-文化,团队,领导力)

--- VOC --- 市场调研的关键步骤 1.> 定义问题 2.>定义结果的准确度 3.>收集数据 4.>分析和解读数据 5.>得出结论 6.>实施 --- 二级市场研究/一级市场研究 --- 定性 > 焦点小组 > 深度访谈 > 人种学(On-Site In-Home) > 客户…

Rust 使用Cargo

Rust 使用技巧 Rust 使用crates 假设你正在编写一个 Rust 程序,要使用一个名为 rand 的第三方库来生成随机数。首先,你需要在 Cargo.toml 文件中添加以下依赖项: toml [dependencies] rand "0.7.3" 然后运行 cargo build&…

C++ 学习系列 -- std::stack 与 std::queue

一 std::stack 与 std::queue 分别是什么? 两者均是 c 中的序列化容器,区别在于: std::stack 元素是先进后出 std::queue 元素是先进先出 二 std::stack 与 std::queue 原理 1 std:statck 2. std::queue 两者底层容器可以是 list 也可以…

数据结构与算法基础(青岛大学-王卓)(8)

哎呀呀,sorry艾瑞波地,这次真的断更一个月了,又发生了很多很多事情,秋风开始瑟瑟了,老父亲身体查出肿瘤了,有病请及时就医,愿每一个人都有一个健康的身体,God bless U and FAMILY. 直…

GraphQL全面深度讲解

目录 一、GraphQL 是什么 二、GraphQL 规范 数据模型 字段 参数 三、运行示例 四、优势和劣势 优势 劣势 一、GraphQL 是什么 GraphQL 是一种用于 API 的查询语言,也是一个基于服务端的运行引擎。 GraphQL 提供了一套完整的规范和描述用于查询 API&#xf…

Sketch mac98.3(ui设计矢量绘图)

Sketch Mac是一款矢量绘图软件,适用于UI设计、网页设计、图标制作等领域。以下是Sketch Mac的一些主要特点: 简单易用的界面设计:Sketch Mac的用户界面简洁明了,使得用户可以轻松上手操作,不需要复杂的学习过程。强大…

【QT】自定义组件ui类添加到主ui界面方法

1.添加自定义组件到项目中 add new选择如下 写好类方法,确定即可 2.将新创建的ui类加入到主ui界面 选中新创建ui类的父类空块,右键选择提升为 选择并添加新创建的类

【目标检测】——Gold-YOLO为啥能超过YOLOV8

华为 https://arxiv.org/pdf/2309.11331.pdf 文章的出发点:FPN中的信息传输问题 1. 简介 基于全局信息融合的概念,提出了一种新的收集和分发机制(GD),用于在YOLO中进行有效的信息交换。通过全局融合多层特征并将全局信…

【DLoopDetector(C++)】DBow2词袋模型loop close学习

0.前言 最近读了两篇论文,论文作者开源了一种基于词袋模型DBoW2库的DLoopDetector算法,自己运行demo测试一下 对应论文介绍:Bags of Binary Words for Fast Place Recognition in Image Sequences 开源项目Github地址:https://gi…

ThreeJS - 封装一个GLB模型展示组件(TypeScript)

一、引言 最近基于Three.JS,使用class封装了一个GLB模型展示,支持TypeScript、支持不同框架使用,具有多种功能。 (下图展示一些基础的功能,可以自行扩展,比如光源等) 二、主要代码 本模块依赖…

vue3学习实战

vue3新增变化 diff算法变化 vue3的diff算法没有vue2的头尾、尾头之间的diff,对diff算法进行了优化,最长递归子序列。 ref VS reactive ref 支持所有的类型,reactive 支持引用类型,array object Map Setref取值、赋值&#xff…

2023-油猴(Tampermonkey)脚本推荐

2023-油猴(Tampermonkey)脚本推荐 知乎增强 链接 https://github.com/XIU2/UserScript https://greasyfork.org/zh-CN/scripts/419081 介绍 移除登录弹窗、屏蔽首页视频、默认收起回答、快捷收起回答/评论(左键两侧)、快捷回…

[CSCCTF 2019 Qual]FlaskLight 过滤 url_for globals 绕过globals过滤

目录 subprocess.Popen FILE warnings.catch_warnings site._Printer 这题很明显就是 SSTI了 源代码 我们试试看 {{7*7}} 然后我们就开始吧 原本我的想法是直接{{url_for.__globals__}} 但是回显是直接500 猜测过滤 我们正常来吧 {{"".__class__}} 查看当前…

Mysql 分布式序列算法

接上文 Mysql分库分表 1.分布式序列简介 在分布式系统下,怎么保证ID的生成满足以上需求? ShardingJDBC支持以上两种算法自动生成ID。这里,使用ShardingJDBC让主键ID以雪花算法进行生成,首先配置数据库,因为默认的注…

Linux shell编程学习笔记4:修改命令行提示符格式(内容和颜色)

一、命令行提示符格式内容因shell类型而异 Linux终端命令行提示符内容格式则因shell的类型而异,例如CoreLinux默认的shell是sh,其命令行提示符为黑底白字,内容为: tcbox:/$ 其中,tc为当前用户名,box为主机…

Spring Boot 技术架构图(InsCode AI 创作助手辅助)

Spring Boot 技术架构是一种用于构建现代应用程序的框架,它可以与各种前端、代理、网关、业务服务、中间件、存储、持续集成和容器服务集成在一起,以创建功能强大的应用程序。 源文件下载链接!!!!&#xff…

BASH shell脚本篇3——字符串处理

这篇文章介绍下BASH shell中的字符串处理的相关命令。之前有介绍过shell的其它命令,请参考: BASH shell脚本篇1——基本命令 BASH shell脚本篇2——条件命令 Bash字符串也是一种数据类型,它用于表示文本而不是数字,它是一组可能…