文章目录
1. 基本信息
相关角色:
- Producer:生产者,向指定Topic发送消息
- Consumer:消费者,从Broker拉取消息消费
- NameServer:路由注册中心,无状态、可集群部署、节点间无通信,负责管理Broker路由信息
- Broker:消息存储与中转服务器,接收、存储及投递消息
1.1 核心组件
组件信息:
- NameServer:
- RouteInfoManager:路由信息管理器,管理如下信息:
- topicQueueTable:Topic下MessageQueue存储的对应Broker信息
- brokerAddrTable:Broker名称及对应的主备节点地址信息
- clusterAddrTable:集群下包含的Broker
- brokerLiveTable:Broker的实时状态,如判断Broker是否存活的最后心跳时间
- NettyRemotingServer:Netty远程调用器,和Broker进行网络交互
- ScheduledExecutorService:定时任务线程,每隔10s检查一次brokerLiveServer,若120s未上报心跳则移除
- KVConfigManager:主要用于管理顺序消息Topic,Key=Topic名称,Value=所属Broker,增删改时会直接持久化
- RouteInfoManager:路由信息管理器,管理如下信息:
- Broker:
- 元数据管理:
- TopicConfigManager:管理Topic配置信息,如读写队列数和权限等
- ConsumerOffsetManager:持久化管理每个消费组的消费进度
- SubscriptionGroupManager:管理消费者订阅关系,包括重试队列和死信队列
- 消息存储管理:
- CommitLog:消息物理存储主体
- ConsumeQueue:消息逻辑消费队列,即MessageQueue
- IndexFile:消息查询索引
- 客户端管理:
- ClientManager:管理连接到本Broker所有的Producer和Consumer
- PullMessageProcessor:处理消费者拉取消息请求
- SendMessageProcessor:处理生产者发送消息请求
- 高可用服务:负责Master和Slave之间的数据同步
- 元数据管理:
组件交互:
- NameServer:
- Broker:Broker主动向NameServer发送心跳请求,NameServer被动保存维护Broker信息
- Producer:从NameServer拉取Topic对应Broker信息和其下所有MessageQueue
- Consumer:从NameServer拉取Topic对应Broker信息和其下所有MessageQueue
- Broker:
- Producer:负载均衡后向对应Broker发送消息
- Consumer:负载均衡后想对应Broker拉取消息
1.2 Topic和MessageQueue管理
Topic创建模式:
- 自动创建:生产不推荐使用
- 效果:生产者首次发送消息时创建
- 配置:autoCreateTopicEnable=true
- 实现方式:
- Broker启动准备:Broker创建TBW102,默认MessageQueue=8
- 获取路由信息:生产者从NameServer查询到路由TBW102
- 发送消息:发送时使用TBW102模板替换原Topic
- 创建与注册:Broker收到消息后创建Topic,并注册到NameServer
- 手动模式:
- 集群模式:
- 效果:每组Master Broker创建相同数量MessageQueue
- 参数:-c
- 分配机制:轮询机制,不同组别均匀的分配MessageQueue
- Broker模式:
- 效果:可针对每个Broker指定不同MessageQueue数量
- 参数:-b
- 集群模式:
Topic扩容和缩容:
- 原则:
- 优先保证数据安全稳定:不轻易移动或删除已包含消息的现有队列
- 扩展由于收缩:增加队列是自然且安全的操作,而删除队列是需要谨慎处理的
- 负载均衡:分配队列时尽可能采用轮询分配方式,实现均匀分布
- 读写队列分离:读写队列分离提供了平滑缩容的能力
- 底层原理:
- 执行指令:组A的Broker执行修改Topic队列指令
- 修改Topic队列信息:修改本地Topic的队列信息
- 同步给NameServer:组A的Broker同步修改后的Topic信息给NameServer
- 同步Topic队列:组B的Broker从NameServer获取到Topic最新的队列信息
- 算法判断:根据扩容和缩容的原则计算分配队列
- 执行操作:根据算法分配结果执行扩容或缩容
- 初始状态:2组Broker,各分配了4个MessageQueue,一共8个MessageQueue
- 扩容:
- 目的:新增1组Broker及3个MessageQueue
- 结果:原2组Broker不变,新增的Broker分配3个MessageQueue
- 缩容:
- 目的:减少2个MessageQueue
- 操作方式:
- 减小写队列:减少2个写队列
- 等待消费:多出来的队列消息已被消费
- 减小读队列:减少2个读队列
- 结果:2组Broker各减少1个MessageQueue
ConsumeQueue和MessageQueue:
- ConsumeQueue定义:物理存储层面的实际队列
- MessageQueue定义:逻辑层面的队列,实际不存在,分为写队列和读队列:
- 写队列:生产者发送消息的队列视图,决定可往哪些队列发送消息
- 读队列:消费者拉取消息的队列视图,决定可从哪些队列拉取消息
- 对应关系:
- 创建规则:ConsumeQueue数量和哪些ConsumeQueue可写入消息由写队列决定
- 生命周期:缩容后,ConsumeQueue不会立即删除,等消息消费完并且过期才删除
- 可见性:有多少ConsumeQueue可被消费取决于读队列数量
1.3 特殊Topic
- SCHEDULE_TOPIC_XXXX:延迟消息的特殊Topic,XXXX为对应的延迟等级,5.0之前使用,5.0后使用时间轮取代
- RMQ_SYS_TRANS_HALF_TOPIC:事务消息中存储半消息的Topic,代表预提交成功
- RMQ_SYS_TRANS_OP_HALF_TOPIC:事务消息操作记录Topic,记录半消息的提交/回滚操作记录
- %RETRY%:为每个消费者组创建的消息重试Topic,消息消费失败后写入此Topic等待消费
- %DLQ%:死信队列Topic,消息经过最大重试次数后仍失败,写入该队列
- TBW102:自动创建Topic模板的Topic,autoCreateTopicEnable=true时,且Topic不存在以该Topic为模板去创建目标Topic
- RMQ_SYS_TRACE_TOPIC:消息轨迹Topic,开启消息轨迹跟踪功能时,追踪数据写入该Topic
对应消息类型:
- 普通消息:由生产者确定发送到具体的MessageQueue
- 顺序消息:由生产者根据业务key指定发送到具体的MessageQueue
- 延时消息:
- 4.X:指定延迟等级后消息存放到对应的Topic
SCHEDULE_TOPIC_XXXX中,再分发给消费者 - 5.X:保存到同一个MessageQueue中,根据时间轮分配算法给消费者
- 4.X:指定延迟等级后消息存放到对应的Topic
- 事务消息:
- 半消息:消息存储在Topic
RMQ_SYS_TRANS_HALF_TOPIC下,预提交成功 - 事务确认:生产者向Broker发送Commit或Rollback请求
- Commit:将半消息转移到Topic下的MessageQueue中
- Rollback:删除半消息
- 事务回查:Broker主动回查生产者消息状态,根据结果执行最终操作
- 半消息:消息存储在Topic
1.4 消息处理流程
- 消息接收处理:
- 获取路由信息:生产者通过写队列得知可往哪些队列发送消息
- 接收与验证:Broker接收消息后校验Topic是否存在、消息体是否超限及是否有写入权等;
- 刷盘:消息顺序追加到CommitLog文件末尾
- 主从同步:若为同步复制,会等待从Broker写入CommitLog成功
- 返回结果:向生产者响应SendResult,包含了MessageID
- 消息构建:消息写入CommitLog后后台线程完成构建
- 构建ConsumeQueue:监听到CommitLog的新增内容,解析出Topic和QueueID,并追加到对应的ConsumeQueue文件
- 构建IndexFile:将新增消息的MessageID存储索引文件中
- 消费消息:
- 获取路由信息:消费者通过读队列得知可从哪些队列拉取消息
- 拉取消息:消费者指定Topic、QueueID及消费偏移量(offset),offset指向ConsumeQueue的位置
- 查询ConsumeQueue:Broker查找到对应文件,并获取消息在CommitLog的物理偏移量
- 读取CommitLog:根据物理偏移量从CommitLog获取完整消息内容
- 返回消息与确认:消费者获取到消息完成业务处理后,返回一个ACK确认消息,Broker更新ConsumeQueue的消费进度
1.5 Broker配置
- brokerClusterName:集群名称,决定多个不同Broker组是否在同一集群
- brokerName:名字相同分配在同一Broker组
- brokerId:0表示master,大于0标识slave,需唯一
- brokerRole:
- SYNC_MASTER:master可配,同步复制
- ASYNC_MASTER:master可配,异步复制
- SLAVE:从节点角色
2. 持久化
运行时配置存储:
- CommitLog:消息物理存储主体
- 物理路径示例:./store/commitlog/
- 作用:所有Topic和队列的消息都按到达顺序混合存储在此
- 特点:顺序写入;文件滚动;亿G级数据量
- 文件名称:文件中第一条消息的偏移量
- ConsumeQueue:消息逻辑消费队列,即MessageQueue
- 物理路径示例:./store/consumequeue/{TopicName}/{QueueId}/
- 作用:作为CommitLog的索引,按Topic和MessageQueue分目录存储
- 特点:固定格式;异步构建;快速定位
- 文件名称:文件中第一条消息的偏移量
- IndexFile:消息查询索引
- 物理路径示例:./store/index/
- 作用:提供基于Message Key或时间范围的查询能力
- 特点:哈希索引;固定大小
- 文件名称:创建文件时的时间戳
- config:存储运行时元数据和配置
- 物理路径示例:./store/config/
- 文件列表:
- consumerOffset.json:记录集群消费模式下每个消费组对每个MessageQueue的消费偏移量;每5s定时持久化
- subscriptionGroup.json:存储订阅了该Broker上Topic的消费者组信息,如是否允许消、重试次数等;变更时持久化
- topics.json:存储该Broker上所有Topic配置信息,如名称、读写队列数量等;变更时持久化
- delayOffset.json:跟踪延时队列拉取进度;每10s定时持久化
- checkpoint:
- 物理路径示例:./store/checkpoint
- 作用:存储检测点,记录CommitLog、ConsumeQueue和IndexFile文件最后刷盘时间戳。重启时根据时间戳检查文件完整性
- abort:
- 物理路径示例:./store/abort
- 作用:正常关闭时会被删除。若启动时发现有该文件,数据恢复阶段会使用严格校验和修复流程
- lock:
- 物理路径示例:./store/lock
- 作用:保证Broker进程对文件访问的互斥,防止并发错误
磁盘清理机制:
- CommitLog:
- 基于时间保留:消息默认保留3天,超过3天的标记为过期,通过
fileReservedTime配置 - 基于定时任务清理:默认每天凌晨4点清理过期消息,通过
deleteWhen配置 - 基于磁盘空间清理:
- 空间警戒(≥75%):立即清理过期消息
- 强制清理(≥85%):无论消息是否过期,从最旧消息开始强制清理,直到低于阈值
- 拒绝写入(≥90%):Broker会变为只读,拒绝新消息写入
- 手动清理过期消息:使用管理工具手动触发清理操作,紧急情况可使用
- 基于时间保留:消息默认保留3天,超过3天的标记为过期,通过
- ConsumeQueue和IndexFile:触发CommitLog时同时清理
- 清理方式:都是以文件为单位删除的
- CommitLog:文件中最早消息过期就删除该文件;若文件中部分过期部分有效保留
- ConsumeQueue:文件名偏移量对应的消息被删除即删除该文件,否则保留
- IndexFile:文件名时间戳大于过期时间即删除,否则保留
3. 高可用
3.1 Broker数据同步
同一组中的主从Broker所有数据都是一致的,Slave是Master的数据副本,包括以下数据:
- Topic:Broker包含的Topic
- MessageQueue:Topic下所创建的消息队列
- 消费者组:消费者组及其中消费者的订阅关系
- 消费进度:所有消费者组的消费进度
Broker的主从同步都是slave主动向master发起连接请求或拉取数据,设计核心目的:
- 简化设计:角色单一化,只需被动接收请求,避免slave状态对master的干扰
- 减轻负担:master主要承担消息的写入职责,需要减少维护slave状态的工作量
- 方便扩展:数据同步主动权在slave,扩展时slave只需要管理自身数据即可
主从Broker数据同步机制:
- 消息数据同步:
- 同步内容:CommitLog文件中的消息
- 同步机制:slave通过TCP长连接持续向master上报偏移量(offset),master返回之后的消息
- 核心目的:保证消息高可靠性和高可用性,避免消息丢失
- 元数据同步:
- 同步内容:Topic、消费者偏移量和订阅关系等系统配置信息
- 同步机制:slave每隔10s向master发起请求同步全量数据并覆盖本地数据
- 核心目的:保证slave的系统元数据和master保持一致,以便后续能顺利成为master
消息复制机制:master把消息同步给slave
- 异步复制:性能优先,消息写入CommitLog后即返回结果,后台线程控制消息同步给其它从Broker
- 同步复制:可靠性优先,消息写入主Broker的CommitLog且等待至少有一个从Broker写入CommitLog后返回结果
集群模式下,所有消费者的ACK都是发送给Master Broker,再通过消息复制机制同步给Slave Broker,广播模式消费进度存储在消费者本地
消息堆积:
- 判定条件:消费者拉取偏移量和CommitLog最大消息偏移量差值是否大于物理内存40%(默认)
- 触发操作:master会建议该消费者去配置
suggestWhichBrokerId对应的slave拉取消息 - 完整流程:
- 消费者从master拉取消息时判定为消息堆积,返回建议slave id
- 消费者收到建议slave id后更新缓存,后续从slave拉取消息
- 消费者消费消息后发送ACK给master
- master收到ACK后更新消费进度并同步给slave
- slave从master同步元数据
- 消费者拉取消息时slave根据元数据判定master不存在消息堆积,返回master id
- 消费者收到master id,后续从master拉取消息
3.2 故障恢复
故障恢复方式:
- 手动操作:
- master恢复方式:修改slave配置后重启slave恢复
- 条件:无,支持1主多从
- DLedger选举:
- master恢复方式:同组Broker使用DLedger算法自动推举master恢复
- 条件:至少1主2从,同组Broker数量为奇数
版本划分:
- 4.5之前:仅支持手动操作
- 4.5+:支持手动操作和DLedger选举
4. 部署信息
启动顺序:先启动所有NameServer,再启动各个Broker
部署原则:同一组Broker优先1主1从,扩容时新增一组Broker,不推荐1主多从
部署场景:
- 需求:2台NameServer,2台主Broker,2台从Broker
- 机器数量:最少需要2台,如下:
- node1:NameServer1,Broker-master1,Broker-slave2
- node2:NameServer2,Broker-master2,Broker-slave1
- 操作流程:
- 分别启动NameServer
- 配置Broker中的NameServer地址
- 启动Broker
扩容方式:
- 机器分布现状:假设机器分布情况如下:
- node1:
NameServer1,Broker-master1,Broker-slave2 - node2:
NameServer2,Broker-master2,Broker-slave1
- node1:
- 扩容NameServer:新增1台NameServer
- 启动新增
NameServer3 - 依次更新原Broker的NameServer列表配置
- 空闲时依次更新生产者和消费者的NameServer配置
- 启动新增
- 扩容Broker:分别新增1台主Broker和从Broker
- 设置node2机器的从Broker
Broker-slave1为只读,等无消息被消费时进行下一步 - node3机器启动新增主Broker
Broker-master3和Broker-slave1 - node2机器启动新增从Broker
Broker-slave3 - 手动分配现有Topic队列到新增Broker
- Consumer和Producer通过自动发现机制获取最新拓扑信息
- 设置node2机器的从Broker
- 扩容后机器分布:
- node1:
NameServer1,Broker-master1,Broker-slave2 - node2:
NameServer2,Broker-master2,Broker-slave3 - node3:
NameServer3,Broker-master3,Broker-slave1
- node1:
- 扩容Topic:可直接扩大Topic下的读写队列数量
缩容方式:
- 现状:假设机器分布情况如下:
- node1:
NameServer1,Broker-master1,Broker-slave2 - node2:
NameServer2,Broker-master2,Broker-slave3 - node3:
NameServer3,Broker-master3,Broker-slave1
- node1:
- 缩容NameServer:减少1台NameServer
- 空闲时依次更新生产者和消费者的NameServer配置
- 依次更新原Broker的NameServer列表配置
- 停止
NameServer3
- 缩容Broker:分别减少1台主Broker和从Broker
- 设置下线Broker
Broker-master3、Broker-slave3和Broker-slave1为只读,不可写 - 监控Broker消息积压情况,当
Broker-master3入口TPS(InTPS)为0且Diff为0准备下一步 - 先后停止
Broker-slave3、Broker-slave1和Broker-master3 - 在node2机器上启动从Broker
Broker-slave1
- 设置下线Broker
- 缩容后机器分布:
- node1:
NameServer1,Broker-master1,Broker-slave2 - node2:
NameServer2,Broker-master2,Broker-slave1
- node1:
- 缩容Topic:先减少写队列数量,待多出来的读队列消息为空时再减少读队列数量
主从Broker设置只读权限差异:
- 只读权限作用:运维停机前的必要指令,在NameServer路由表中标记为只读
- Master Broker:生产者不可写入,对消费者仍可见且可读取已写入的消息
- Slave Broker:触发流量切换,逐渐将消费者迁移到其它Broker,最终等同于不可用

1109

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



