文章目录
1. 基本信息
1.1 基本组件
- NameServer:路由注册中心,无状态、可集群部署、节点间无通信,负责管理Broker路由信息
- Broker:消息存储与中转服务器,接收、存储及投递消息
- Producer:生产者,向指定Topic发送消息,支持同步、异步、单向三种发送模式
- Consumer:消费者,从Broker拉取消息消费
- 拉取模式:支持Push和Pull拉取模式
- 消费模式:集群消费和广播消费
M
1.2 核心概念
- Message:消息,传输信息最小单位,包含Topic、Tag、Body和Properties
- Topic:主题,消息的一级分类,Producer向指定Topic发送消息,Consumer订阅特定Topic消息
- Tag:标签,Topic下的二级分类,用于对同一主题消息进行更细粒度的过滤和分类
- MessageQueue:消息队列,一个Topic在物理上会被分为多个MessageQueue,消息存储在MessageQueue中。其是负载均衡和并行消费的基本单位
- Consumer Group:消费者组,由多个Consumer组成
- 集群消费:消息只会被组内一个消费者消费
- 广播消费:消息会被组内所有消费者消息
- Producer Group:生产者组,由多个Producer组成
- 事务消息:4.X版本强依赖于统一生产者组来实现事务状态查询;5.X不再强依赖
- 非事务消息:不强依赖,提供消息生产标签功能
- Properties:扩展机制,实际是键值对Map<String, String>集合,用于附带额外信息
- TAGS:对应Tag标签,通过
setTags()设置 - KEYS:消息业务键,用于查询和追踪消息,通过
setKeys()设置 - DLAY:消息延迟级别,用于指定延迟消息投递时间,通过
setDelayTimeLevel()设置 - TRAN_MSG:标识为事务消息,发送事务消息自动标记
- RETRY_TOPIC:重试Topic,用于重试消息
- REAL_TOPIC:消息的真实Topic,用于延迟消息
- RECONSUME_TIME:消息重试次数,记录消息被重新投递的次数
- 自定义属性:设置额外的属性值,通过
putUserProperty()设置
- TAGS:对应Tag标签,通过
2. 生产者
工作流程:
- 启动:初始化并和NameServer建立连接
- 确定发送Topic:开发者确定发送消息给哪个Topic
- 获取路由信息:
- 首次使用Topic发送消息:生产者发送消息检查本地是否有Topic缓存,没有则从NameServer查询Topic路由信息,获得Topic分布在哪些Broker以及有哪些MessageQueue
- 后续维护:本地缓存后,定时任务每30s更新一次本地缓存Topic
- 选择MessageQueue:根据负载均衡策略为消息选择目标队列
- 发送消息:向确定的MessageQueue发送消息
- 处理响应:根据发送模式处理Broker响应结果
- 流控处理:若Broker积压消息过多,会返回流控错误响应215或530,但流控措施需要开发者制定
- 失败重试:若发送失败,生产者会自动重试,重试时避开上次失败的Broker
- SEND_OK:发送成功,且Broker刷盘和主从复制均已完成
- FLUSH_DISK_TIMEOUT:发送成功,但刷盘失败,但消息可能丢失
- FLUSH_SLAVE_TIMEOUT:发送成功,但主从同步超时,但消息可能丢失
- SLAVE_NOT_AVAILABLE:发送成功,但无可slave,但消息可能丢失
- 抛出异常:发送失败,此时会触发重试
2.1 关键参数
- producerGroup:生产者组,自定义
- namesrvAddr:NameServer地址列表
- sendMsgTimeout:发送消息超时时间,默认3000ms
- retryTimesWhenSendFailed:同步发送失败时的重试次数,默认2次
- compressMsgBodyOverHowmuch:触发消息体压缩阈值,默认4096=4KB
- maxMessageSize:允许发送的最大消息大小,默认4M
2.2 生产者类型
- DefaultMQProducer:默认生产者,用于发送普通消息,有三种发送模式:
- 同步消息(Sync Send):默认,发送后等待Broker返回确认结果,可靠性最高,吞吐量较低
- 异步消息(Async Send):发送后立即返回,通过回调函数获取结果,提高吞吐量
- 单向消息(Oneway Send):只发送消息,不等也不关心结果,速度最快,可靠性最低
- TransactionMQProducer:事务生产者,用于发送事务消息,依赖于事务监听器
TransactionListener,基于两阶段提交(2PC) 以及 状态回查机制实现:- 半消息:第一阶段,消息预发送
- 同步发送一条半消息,消息标记为
TRAN_MSG=true - Broker使用特殊Topic存储,此时无法消费
- 返回ACK给生产者
- 同步发送一条半消息,消息标记为
- 本地事务执行:第二阶段,本地事务执行与二次确认
- 收到消息的ACK后执行本地事务
- 根据本地事务执行结果向Broker发送二次确认消息,Broker对应操作:
- COMMIT_MESSAGE:本地事务成功,恢复消息到原Topic,此时可消费
- ROLLBACK_MESSAGE:事务失败,Broker丢弃半消息
- UNKNOW:状态未知,等待后续事务状态回查机制
- 状态回查:当、或状态回查返回UNKNOW触发
- 触发条件:二次确认或状态回查返回UNKNOW;二次确认超时未响应
- 最大回查次数:Broker配置,每次超时或返回UNKNOW时+1
- 事务超时时间:Broker配置,半消息二次确认的最大等待时间
- 回查时间间隔:Broker配置,每隔一段时间扫描需要回查的消息
- 半消息:第一阶段,消息预发送
2.3 消息类型
- 普通消息:最基础的,无特殊特性
- 顺序消息:根据参数人为指定消息要发送到具体的MessageQueue,一般搭配
MessageQueueSelector实现 - 延时消息:
setDelayTimeLevel()设置发送延时投递消息- 固定延迟级别:4.X版本及之前的使用,实现流程:
- Broker为不同延时等级分别创建了MessageQueue,不同延时等级的MessageQueue都有对应的定时任务
- Broker接收到延时消息后计算得出对应MessageQueue并投递
- 使用对应MessageQueue的定时任务轮询消息
- 轮询到消息后投递到原始的Topic和MessageQueue并由消费者消费
- 分层时间轮:5.X版本开始支持,可以配置24h内任意延迟时间,单位毫秒
- 固定延迟级别:4.X版本及之前的使用,实现流程:
- 事务消息:使用事务生产者发送,通过二阶段提交(2PC) 和 状态回查机制实现
2.4 分层时间轮
- 算法思想:通过固定环形数组结构来模拟时钟,数组每个槽位代表一个时间间隔,任务根据延迟时间分配到合适的槽位,随着数组遍历,执行到达槽内的所有任务
- 数据结构:
- 第1层:毫秒级,每1ms往后遍历一个槽位,数组索引范围[0,1000)
- 第2层:秒级,每1s往后遍历一个槽位,数组索引范[0,60)
- 第3层:分钟级,每1min往后遍历一个槽位,数组索引范[0,60)
- 第4层:小时级,每1h往后遍历一个槽位,数组索引范[0,24)
- 数据槽位计算:
- 槽位数量:层级槽位数量设为N,
- 当前槽位:时间轮指针所指槽位索引设为I
- 计算公式:同层级数据设为M,计算公式为
(I+M)/%N
- 示例:以3h 25min 49s 754ms为例来计算其时间轮分布情况
- 第4层:假设时指针是5,插入3h,槽位为
(5+3)%24=8,经过3h到达槽位8 - 第3层:假设时针是53,插入25min,槽位为
(53+25)%60=18,经过25min到达槽位18 - 第2层:假设时针是39,插入49s,槽位为
(39+49)%60=28,经过49s到达槽位28 - 第1层:假设时针是20,插入754ms,槽位为
(20+754)%1000=774,经过754ms到达槽位774
- 第4层:假设时指针是5,插入3h,槽位为
2.5 负载均衡策略
- 核心逻辑:消息需要发送到MessageQueue中,MessageQueue和Broker是绑定的,确定了MessageQueue就确定了Broker
- 策略实现:
- 轮询策略:Round Robin,按顺序依次选择MessageQueue,循环使用
- 哈希策略:Hash-based,根据业务键进行哈希,对MessageQueue取模,确保相同业务键消息的顺序性
- 随机策略:Random,完全随机从MessageQueue中选择一个
- 自定义策略:自行实现
MessageQueueSelector中选择队列逻辑
Producer调用方法的对应关系:
- 说明:负载均衡策略并非底层Producer做的智能判断,而和开发者调用的方法有关
- send(Message):
- 负载均衡策略:轮询策略
- 特点:
sendLatencyFaultEnable延迟故障隔离配置为true,重试自动避开近期故障Broker;配置为false则正常轮询
- send(Message,MessageQueue):
- 负载均衡策略:自定义策略
- 特点:开发者自行指定MessageQueue发送消息,若该MessageQueue对应的Broker故障,则消息丢失
- send(Message,MessageQueueSelector,Object):
- 负载均衡策略:依赖于
MessageQueueSelector实现类 - 特点:官方有两种即用策略:哈希策略和随机策略,除此之外为自定义策略
- 负载均衡策略:依赖于
2.6 维护路由信息
连接NameServer:
- 启动时:
- 选择策略:从列表中随机选取一个
- 连接失败:连接失败按顺序连接下一个地址
- 全部失败:
start()方法抛出异常
- 运行中:
- 选择策略:若当前连接因为网络抖动或NameServer宕机不可用,触发重连机制
- 重连机制:按顺序选择下一个NameServer进行连接
- 全部失败:生产者后台持续重试连接,但此时使用生产者发送消息调用会抛出异常
拉取Topic路由信息:
- 核心思想:使用懒加载方式获取并缓存Topic路由信息
- 启动时:仅启动每30s的定时任务
- 运行中:
- 拉取时机:首次向Topic发送消息时
- 拉取条件:检查本地缓存,不存在或无效则同步向NameServer拉取路由信息并缓存在本地
- 更新机制:每隔30s扫描本地已缓存的Topic路由信息
Broker的Topic信息发生变化后,生产者也是通过每隔30s扫描本地已缓存的Topic路由信息再去做更新
2.7 流量控制
215流控响应码:
- 含义:客户端发送配额耗尽
- 触发原因:生产者发送速率超过Broker单位时间发送量或字节树大小限制,如:
- 批量任务瞬间大量发送:跑批作业短时间内发送成千上万条消息
- 生产者并发过高:多个线程向同一个Topic疯狂发送消息
- 消息体过大:单条消息过大,虽然条数不多,但触发了字节数限制
- 处理方式:生产者主动限流,调整发送策略如进行发送限流或扩容Broker配置
530流控响应码
- 含义:系统请求过多
- 触发原因:系统容量超限,一般是消费者的消费速度跟不上生产者发送速度
- 处理方式:重点关注消费者堆积情况,若都是正常消费则需扩容Broker配置
3. 消费者
工作流程:
- 启动:校验配置并从NameServer获取路由信息
- 负载均衡:获取Topic的所有MessageQueue并根据分配策略更新到本地缓存
- 拉取请求:分配到本地的每个MessageQueue都会创建一个
PullRequest对象并放入待拉取队列 - 流控检查:真正发起网络请求前,检查本地消息缓存队列,若积压消息过多则等待50ms再尝试消息拉取
- 消息拉取:轮询待拉取请求队列,向Broker发送拉取请求
- 消费池化:将拉取到消息封装成
ConsumeRequest并提交到线程池 - 执行监听器:线程池的线程调用往Consumer注册的
MessageListener - 返回消费状态:业务逻辑执行完成后返回对应状态:
- CONSUME_SUCCESS:成功
- RECONSUME_LATER:失败,稍后重试
- 提交偏移量:完成消费后必须提交消费进度,不同消费模式操作不同:
- 集群消费:提交给Broker后保存在对应的Consumer Group中
- 广播消费:在消费者本地管理
消费重试不会立即重新投递,重试间隔会根据重试次数而逐渐加长
3.1 关键参数
- consumerGroup:消费者组,要求同一消费逻辑的消费者相同
- namesrvAddr:NameServer地址列表
- messageModel:消费模式,决定同一消费组不同实例消息如何分发
- CLASTERING:集群模式,默认值,一条消息只会被组内其中一个消费者消费
- BROADCASTING:广播模式,一条消息会被组内每一个消费者消费
- consumeFromWhere:消费起始点策略,控制消费者首次启动从什么位置开始消费
- LAST_OFFSET:默认值,从最新偏移量开始消费
- FIRST_OFFSET:从队列最早的消息开始消费
- TIMESTAMP:指定消费时间戳之后的
3.2 消费模式
消费模式将决定消费者如何分配Topic下的MessageQueue以及确保消费者的负载均衡
- 广播模式:
- 负载均衡:无,每个消费者分配的MessageQueue相同
- 偏移量管理:消费后实时更新偏移量到本地内存,定时任务每5s把偏移量持久化到本地磁盘,以方便后续启动时续上偏移量
- 消息重试:不支持,消费失败后不会重试
- 特点:
- 不支持顺序消息:若使用
MessageListenerConcurrently会抛出异常,只能使用MessageListenerConcurrently - 负载随消费者数量增长:随消费者增长网络带宽和Broker负载都会提升
- 不支持顺序消息:若使用
- 集群模式:
- 负载均衡:共有六种,和消费者类型有关,通过
setAllocateMessageQueueStrategy()设置 - 偏移量管理:定时任务每5s(默认)向Broker提交一批偏移量给所属消费者组,可手动调用提交,后续拉取消息时Broker以消费者组偏移量返回消息
- 消息重试:支持,最多配置16次重试,超过后进入死信队列,默认16次
- 特点:
- 消息分发:一条消息只会被同一消费组的一个消费者消费
- 重平衡:消费者数量发送变动时会触发重平衡以保证负载均衡
- 数量限制:消费者需要≤Topic下的MessageQueue数量,多出来的实例会空闲
- 消费组间隔离:同一条消息会被分配到所有消费组,各组消费进度独立
- 负载均衡:共有六种,和消费者类型有关,通过
3.3 消费者类型
不管是何种消费者,本质都是消费者主动从Broker拉取消息,而非Broker主动推送
- DefaultMQPushConsumer:默认,推荐使用,采用长轮询机制模拟推送效果,若Broker没有新消息,则持续15s的长轮询,期间有新消息则返回;若拉取时有新消息则直接返回
- DefaultMQPullConsumer:需主动调用
pull()方法拉取消息,拉取间隔和机制需自行实现,现已不推荐使用,不过多解读 - DefaultLitePullConsumer:4.6.X引入,提供更轻量、更高效的手动拉取实现,资源开销更低
- 拉取方法:调用
poll(),支持设置拉取超时时间 - 拉取数量和进度控制:支持设置一次性拉取N条消息,可自主提交消费偏移量
- 拉取方法:调用
- SimpleConsumer:5.X引入,提供更原子性的方法,可以获取消息、自由处理消息以及确认消息
严禁在相同的消费者组使用不同的消费者类型,否则会导致消息消费异常
3.3.1 DefaultMQPushConsumer
参数配置:
- consumeThreadMin:默认20,消费线程池核心线程数
- consumeThreadMax:默认64,消费线程池最大线程数
- pullBatchSize:默认32,单次拉取的最大消息条数
- pullInterval:默认0,拉取消息间隔(ms),0标识无间隔长轮询
- pullThresholdForQueue:默认1000,MessageQueue对应本地缓存的最大消息数量
- pullThresholdSizeForQueue:默认100MB,MessageQueue对应本地缓存的最大消息总大小
- maxReconsumeTimes:消息最大重试消费次数,超过后进入死信队列
- consumeMessageBatchMaxSize:默认1,单次消费消息最大数量
核心组件:
- RebalanceService:负载均衡服务,根据消费者组内实例数量和Topic的队列数量进行再平衡,并为每个MessageQueue生成一个
PullRequest放入阻塞队列pullRequestQueue - PullMessageService:独立后台线程服务,不断从
pullRequestQueue中取出PullRequest对象 - PullRequest:拉取任务的核心载体,包含了:
- consumerGroup:消费者组
- messageQueue:目标消息队列
- processQueue:临时存放从Broker拉取的消息,作用有四:
- 临时存储:作为消息临时存储快照
- 流量控制:使用
ProcessQueue对消费进度做流控 - 消费进度管理:保存了偏移量和消息的键值对,消费成功后更新偏移量便使用该数据
- 保障顺序消费:做顺序消费时需要对
ProcessQueue加锁以确保同一时间只有一个线程处理消息
- nextOffset:下次要从Broker拉取的偏移量
- MessageListener:消息监听器,仅
DefaultMQPushConsumer使用且必须实现:- MessageListenerConcurrently:
- 定义:并发消费,追求高吞吐量,同一MessageQueue的消息会被多个线程并行消费,对消息顺序不敏感
- 原理:为所有的MessageQueue创建一个共享线程池,拉取到消息后封装成
ConsumeRequest提交给线程池进行处理
- MessageListenerOrderly:
- 定义:顺序消费,保证消息顺序,同一MessageQueue中的消息由单个线程顺序处理,有两点限制:
- 限制:
- MessageQueue有序:只能保证单个MessageQueue中的消息有序,不同MessageQueue的消息是无序的
- 消费模式:仅集群模式有效,广播模式无法使用
MessageListenerOrderly
- 原理:为所有的MessageQueue创建一个共享的单线程线程池,拉取到消息后封装成
ConsumeRequest提交给线程池进行处理
- MessageListenerConcurrently:
流程详解:
- 获取路由信息:连接所有NameServer,随机从一个NameServer拉取Topic的路由信息,后续将一直从该NameServer拉取,直到从NameServer拉取失败再随机一个
- 获取消费者组成员信息:每20s定时任务从Topic路由信息随机选择一个Broker,从Broker获取该消费者组下所有在线消费者ClientID
- 负载均衡:使用配置的负载均衡策略对MessageQueue和ClientID进行排序,并计算出当前消费者应该负责的MessageQueue集合,仅集群模式有
- 创建拉取任务:为当前消费者负责的MessageQueue创建
PullRequest,并提交给PullMessageService的pullRequestQueue队列 - 拉取消息:请求Broker,并根据不同响应结果进行处理:
- FOUND:拉取到消息,更新拉取偏移量nextOffset并把消息存入
ProcessQeueue - NO_NEW_MSG/NO_MATCHED_MSG:无新消息/无匹配消息,更新nextOffset并立即把
PullRequest放回pullRequestQueue队列以开始下次拉取 - OFFSET_ILLEGAL:偏移量非法,重置本地偏移量并停止/丢弃当前队列的所有消息
- FOUND:拉取到消息,更新拉取偏移量nextOffset并把消息存入
- 消息池化:将
ProcessQeueue队列中的消息封装成ConsumeRequest并提交到消费线程中 - 处理消息:使用用户实现的
MessageListener来消费消息,单批大小由consumeMessageBatchMaxSize控制 - 消费成功:使用消费模式对应的偏移量管理方式更新消费进度
- 消费失败:消费失败的消息会被发送回Broker,Broker将其放入重试队列,等待下次消费
- 清理消息缓存:消费成功时从
ProcessQeueue中移除并更新偏移量;消费失败后把消息回传Broker后再从ProcessQeueue中移除
3.3.2 DefaultLitePullConsumer
配置参数:
- autoCommit:是否自动更新本地偏移量,默认true
- pullBatchSize:单次拉取的最大消息数
两种订阅模式:
- Subscribe:自动负载均衡,适合常规场景,会自动从NameServer获取主题的路由信息进行负载均衡,调用
subscribe()方法后开启,会受消费模式的影响 - Assign:手动指定队列,更精细的控制,默认使用,不受消费模式的影响,分配队列有三步:
- 获取所有队列:调用
fetchMessageQueues(Topic)方法获取所有队列 - 分配队列:调用
assign(List<MessageQueue>)方法给当前消费者分配队列 - 确定消费偏移量:调用
seek(MessageQueue,Offset)确定起始消费偏移量
- 获取所有队列:调用
核心组件:
- RebalanceService:同DefaultMQPushConsumer
- PullAPIWrapper:拉取消息的API封装层,负责与Broker通信,发送拉取请求并解析响应
- PullTaskImpl:拉取任何的核心实现(一个Runnable),每个被分配的MessageQueue都有独立的
PullTaskImpl任务,提交到线程池中循环执行,计算偏移量及调用PullAPIWrapper拉取消息等
流程详解:
- 获取路由信息:连接所有NameServer,随机从一个NameServer拉取Topic的路由信息,后续将一直从该NameServer拉取,直到从NameServer拉取失败再随机一个
- 获取消费者组成员信息:每20s定时任务从Topic路由信息随机选择一个Broker,从Broker获取该消费者组下所有在线消费者ClientID
- 负载均衡:使用配置的负载均衡策略对MessageQueue和ClientID进行排序,并计算出当前消费者应该负责的MessageQueue集合,仅集群模式+subscribe有,assign模式需自行分配
- 创建拉取任务:为每个MessageQueue创建
PullTaskImpl任务,循环执行 - 拉取消息:调用
PullAPIWrapper从Broker拉取消息,获得拉取结果对象PullResult,并根据不同响应结果进行处理:- FOUND:拉取到消息,更新拉取偏移量nextOffset并把消息存入和MessageQueue绑定的
ProcessQeueue,随后封装成ConsumeRequest并放入consumeRequestCache缓存队列中 - 其它状态:不做任何事情
- FOUND:拉取到消息,更新拉取偏移量nextOffset并把消息存入和MessageQueue绑定的
- 更新本地偏移量:更新对应MessageQueue的本地消费偏移量
- 处理消息:用户调用
poll()方法,获取本批消息并进行业务处理,此时删除ProcessQeueue和consumeRequestCache队列中的缓存 - 提交偏移量:调用提交方法时,核心是更新本地偏移量。若autoCommit为false,则消费完消息后一定要手动提交偏移量。广播模式下除了更新偏移量,还会持久化一次
- 持久化偏移量:和消费模式相关:
- 集群模式:同步本地偏移量到Broker依赖于每5s执行一次的定时任务
- 广播模式:将本地偏移量持久化到本地
3.3.3 SimpleConsumer
逻辑核心:以MessageQueue为单位拉取消息和提交偏移量,不为MessageQueue做请求合并
配置参数:
- consumerGroup:消费者组
- endpoints:NameServer或Broker地址
- awaitDuration:拉取请求在服务端的阻塞超时时间(长轮询)
- subscriptionExpressions:订阅关系,指定订阅的Topic和Tag
- cachedMessageCount:允许消费者最大同时处理消息数量
- cachedMessageSizeInMiB:允许消费者最大同时处理消息的总大小
核心组件:
- RebalanceService:同DefaultMQPushConsumer
- PullAPIWrapper:拉取消息的API封装层,负责与Broker通信,发送拉取请求并解析响应
流程详解:
- 获取路由信息:连接所有NameServer,随机从一个NameServer拉取Topic的路由信息,后续将一直从该NameServer拉取,直到从NameServer拉取失败再随机一个
- 获取消费者组成员信息:每20s定时任务从Topic路由信息随机选择一个Broker,从Broker获取该消费者组下所有在线消费者ClientID
- 负载均衡:使用配置的负载均衡策略对MessageQueue和ClientID进行排序,并计算出当前消费者应该负责的MessageQueue集合,仅集群模式有
- 流量控制:拉取消息前,根据
cachedMessageCount和cachedMessageSizeInMiB判断当前ProcessQueue是否超过阈值,超过会等待50ms - 拉取消息:调用
receive()直接从MessageQueue对应的Broker拉取消息,每个MessageQueue发送一个请求拉取消息,不会合并发送拉取消息。拉取到的消息会存到ProcessQueue队列中 - 消费消息:若
maxMessageNum是10,消费者分配了N个MessageQueue,最多一次性可拉取N*10条消息,即每个MessageQueue拉取maxMessageNum条消息,最终合并到一个集合中 - 提交偏移量:消费完消息需要手动调用
ack()提交本地偏移量 - 持久化偏移量:和消费模式相关:
- 集群模式:每5s发送提交偏移量请求到MessageQueue对应的Broker
- 广播模式:每5s将本地偏移量持久化到本地
3.4 消费者上下线
启动后每30s向所有的Broker发送心跳检测,Broker通过心跳检测感知消费者上线
心跳信息主要包括消费者组名和消费者ID
若Broker超过2min未收到心跳数据,判定为下线
消费者上下线时Broker会通知所有和该Broker有心跳检测的消费者
3.5 维护路由信息
- 启动时:
- Topic路由信息:拉取订阅Topic对应的所有MessageQueue信息缓存到本地
- 消费者ID:从Broker拉取相同消费者组下所有的消费者ID
- 运行中:
- Topic路由信息:每隔30s拉取Topic全量路由信息更新
- 消费者ID:每隔20s从Broker拉取相同消费者组下所有的消费者ID
3.6 负载均衡
触发时机:
- 启动:消费者刚启动并拉取了Topic路由信息和消费者ID信息后触发
- 定时任务:每隔20s拉取所有消费者ID后和本地缓存比较,不相同则触发
- Broker通知:
- 条件:Broker感知到消费者组下消费者数量发生变动
- 通知对象:消费者组下的所有消费者组
- 特点:所有Broker都会往组下所有消费者发送通知
- 消费者防重:第一次触发负载均衡后,20ms内接收通知将不再执行
负载均衡策略:
- 平均分配:3.X/4.X默认策略,将队列尽可能均匀分配给所有消费者
- 环形分配:按消费者顺序逐个分配队列,循环进行,负载和平均分配一致,只是顺序不一样
- 一致性哈希:使用哈希环分配队列,消费者变动时已分配队列变动较小
- 机房敏感分配:优先将队列分配给和Broker同机房的消费者
- 消息粒度:5.X引入默认策略,允许同组多个消费者同时向一个MessageQueue拉取消息
- 实现原理:
- 服务端加锁:Broker对待分配消息加锁,确保一条消息只对一个消费者可见
- 消费与解锁:消费者拉取消息时,Broker维持消息不可见,提交ack后将消息移除或标记已消费
- 实现原理:
判定数据:
- 优先本地:优先使用本地缓存的Topic路由信息和所有消费者列表信息,保证性能
- 远程兜底:定时从远程拉取Topic路由信息和所有消费者列表信息,实现兜底
不同策略处理方式特点:
- 3.X/4.X:平均分配、环形分配、一致性哈希、机房敏感分配
- 分配单位:MessageQueue
- 并行消费:MessageQueue只能同时被一个消费者消费
- 扩容处理:有MessageQueue数量≥消费者数量的限制
- 5.X:消息粒度(新引入)
- 分配单位:单条消息
- 并行消费:MessageQueue可以同时被多个消费者消费
- 扩容处理:MessageQueue数量和消费者解耦,更灵活

9713

被折叠的 条评论
为什么被折叠?



