RocketMQ高可用集群与Raft协议
一、RocketMQ高可用集群架构演进1.1 传统固定主从架构旧版痛点RocketMQ早期采用固定Master-Slave静态集群架构角色固定启动前手动配置Master、Slave节点角色永久不变写入仅Master所有生产请求走MasterSlave只同步数据、提供读服务故障处理Master宕机后无法自动切换需人工修改配置、重启集群故障恢复慢数据一致性仅支持异步/半同步复制宕机极易出现主从数据不一致、消息丢失核心瓶颈无自动选主、无一致性保障、人工运维成本高、无法支撑生产级高可用。1.2 新版DLedger-Raft高可用架构生产主流RocketMQ 4.8 引入DLedger组件基于标准Raft一致性协议重构Broker集群实现真正的分布式高可用无固定主从集群节点角色动态选举自动产生Leader、Follower故障自动转移Leader宕机集群秒级重新选举新Leader无需人工干预数据强一致基于Raft日志同步机制保证集群多副本数据一致容灾能力极强支持多数派容错少数节点宕机不影响集群读写核心结论DLedger是RocketMQ对Raft协议的工业级落地实现是当前RocketMQ高可用的核心底座。二、Raft协议基础认知与核心角色Raft是一种简单易懂、工程落地性极强的分布式一致性协议相比于复杂的PaxosRaft更轻量化、更适合中间件落地核心解决集群选主、日志同步、数据一致、故障自愈四大问题。先来看个热闹看下Raft协议到底是个什么样子的。网上有个动画文稿是对Raft算法最生动形象的描述。地址http://thesecretlivesofdata.com/raft/从这个动画中可以看到Raft协议是分为两个阶段工作的Election选举和Log Replicaion日志同步。也就是说Raft要解决的其实是两个事情一个是集群中选举产生主节点。另一个是在集群内进行数据同步。Raft算法的基本工作流程是这样的1、多个Server基于他的一致性协议会共同选举产生一个Leader负责响应客户端的请求。2、Leader通过一致性协议将客户端的指令转发到集群所有节点上。3、每个节点将客户端的指令以Entry的形式保存到自己的Log日志当中。此时Entry是uncommited状态。4、当有多数节点共同保存了Entry后就可以执行Entry中的客户端执行提交到State Machine状态机中。此时Entry更新为commited状态。2.1 Raft集群三种角色任意时刻集群每个节点只能处于三种状态之一Leader领导者选举产生。多数派决定。集群唯一写节点全权处理所有读写请求主动同步日志给Follower全局唯一向。Follower 节点发送心跳Follower 收到心跳就不会竞选Leader。Follower跟随者被动接收Leader日志同步、响应心跳不主动处理写请求参与投票选举Candidate候选人Follower超时未收到Leader心跳主动切换为候选人发起新一轮选举拉票Raft协议为了保证同一时刻集群当中最多只会有一个主节点防止脑裂问题还会增加一个Term任期的概念。三者状态变化过程1、所有节点启动时都从Follower状态开始。2、每个Follower设定了一个选举过期时间Election Timeout。Follower持续等待Leader的心跳请求。如果超过选举过期时间就转为Candidate向其他节点发起投票竞选Leader。为了防止所有节点在同一时间过期这个选举过期时间通常会设定为一个随机值一般在150ms到300ms之间。3、Candidate开始新一个任期的选举。每个Candidate会投自己一票然后向其他节点发起投票RPC请求。然后等待其他节点返回投票结果。等待时长也是ElectionTimeout。4、每个节点在每一个任期内有一次投票的资格。他们会响应Candidate的投票RPC请求。按照一定的规则进行投票。返回支持或者不支持。5、Candidate收到其他节点的投票RPC响应之后会重置他的ElectionTimeout继续等待其他响应。一旦某一个Candidate接收到了超过集群一半节点的投票同意结果后就会转为Leader节点。并开始向其他节点发送心跳RPC请求。确认自己的Leader地位。6、其他节点接收到Leader的心跳后就会乖乖的转为Follower状态。Candidate也会转为Follower。然后等待从Leader同步日志。直到Leader节点心跳超时或者服务宕机再触发下一轮选举进入下一个Term任期。2.2 Raft核心三大机制Raft协议所有逻辑只围绕三件事领导者选举集群无Leader时自动投票选出新Leader日志复制同步Leader接收写请求同步日志至多数节点保证数据一致安全性约束保证任何场景下已提交的数据绝对不会丢失、不会回滚2.3 核心时间机制防冲突心跳时间Leader默认定时发送心跳维持集群统治地位选举超时时间Follower随机超时150~300ms避免同时发起选举冲突三、Raft协议完整标准流程面试必背3.1 第一阶段领导者选举流程适用于集群初始化、Leader宕机、网络分区场景。触发条件Follower节点超过超时时间未收到Leader心跳状态切换Follower → Candidate自身任期号term1发起拉票Candidate向集群所有节点发送「投票请求」节点投票规则每个任期只能投一票优先投票给日志更新、任期更新的节点当选LeaderCandidate获得集群多数节点票数过半成功晋升Leader维持统治新Leader立刻向全网发送心跳阻止其他节点发起新选举关键规则Raft集群必须过半存活才能选举成功、正常提供服务多数派机制。3.2 第二阶段日志同步复制流程选举完成后集群进入稳定同步状态保证多副本数据一致。客户端写入所有写请求统一路由至Leader节点Leader本地落盘Leader将请求封装为日志条目本地持久化同步FollowerLeader通过心跳/同步线程将日志复制给所有Follower多数派提交日志同步至过半节点判定为「已提交日志」响应客户端提交成功后Leader返回写入成功给客户端异步补全继续同步剩余少数节点最终集群数据完全一致3.3 第三阶段故障恢复与日志对齐针对节点宕机、重启、网络抖动场景Raft自动修复数据差异落后节点重启后自动对比本地日志与Leader日志的任期、索引Leader主动推送缺失日志覆盖脏数据、补齐缺失数据保证落后节点快速追上集群最新状态无数据丢失、无数据错乱四、Raft协议底层基础实现机制核心原理Raft算法的基础数据结构:所有节点都需要的信息currentTerm服务器当前的任期votedFor当前任期内投票给了谁。log[]日志条目Entry。每个Entry 要包含Command客户端指令term任期idxEntry 的偏移量。commitlndex标记为commited的 Entry的索引。记录消息同步的进度。lastApplied已执行完Command的Entry索引。记录往状态机提交的进度。lastAppliedcommitIndex。这两个主要是提交到状态机需要Leader上的特有参数:·nextlndex[]给每个Follower同步到了哪一条Entry。记录与follower 的同步进度。matchlndex[]给每个 Follower已经复制到了哪一条Entry。主要是要记录有哪些Entry发给Follower,正在等待 Follower 确认中。然后看RPC请求最为核心的有三个。第一个是Candidate投票的RPC请求。第二个是Leader发送的心跳请求。第三个是Leader发送的日志同步请求。对于投票请求主要请求参数·term当前任期candidateld投票的候选人ID。lastLogIndex候选人的最后日志Entry索引。last logo term候选人最后日志条目的任期号。前两个参数是必须的。后两个参数主要是当主从发生切换时可以用来找出最新的Candidate。主要响应参数:term当前任期号voteGranted投票结果。是否支持当前Candidate当选为Leader。对于后两个请求都是有Leader往Follower发送。**其实可以合并为一种请求。心跳请求不带日志条目而同步日志请求带日志条目。Follower只要判断下有没有日志条目就可以区分是哪种请求。主要请求参数:term当前领导者的任期leaderld当前领导者的ID。entries[]要同步的日志条目。心跳请求就传空。同步消息请求则可以支持批量同步。leaderCommit领导者已知已提交的最高的日志条目的索引。主要是Follower要知道新的条目是要从哪里开始同步。为了安全起见论文中还建议将上一条Entry的Index以及Term发送过来。主要还是用来协助Follower定位 Entry主要响应参数:term当前任期。success:响应是否成功。4.1 核心数据单元日志条目LogEntryRaft所有一致性能力全部依托有序日志实现每条日志固定结构index日志全局有序索引唯一递增term日志所属任期号用于判断日志新旧data实际业务数据RocketMQ中为消息数据、元数据commitIndex当前节点已提交的最大日志索引核心思想日志有序、任期递增、多数提交、永不回滚。4.2 日志新旧判断规则重中之重Raft投票、日志同步的核心判断逻辑优先比较任期term任期大的日志更新任期相同比较索引index索引大的日志更新保证只有拥有最新完整数据的节点才有资格当选Leader杜绝数据丢失。4.3 Raft安全性核心规则面试绝杀已提交日志永不丢失只要日志被多数节点同步提交永久生效新Leader必须包含该日志旧Leader无法复辟旧Leader重启后发现任期落后自动降级为Follower同步新集群数据日志强一致性同一index、同一term的日志内容绝对一致五、RocketMQ中Raft协议的落地实现DLedger架构RocketMQ没有直接使用原生Raft而是自研轻量化Raft实现框架DLedger专门适配消息队列存储场景是Raft协议的工程级定制版。5.1 DLedger核心定位DLedger Raft一致性协议 消息日志存储适配 自动故障转移解决原生Raft不适配MQ的问题海量日志堆积、高吞吐写入、磁盘持久化、秒级切换。5.2 DLedger集群架构规范最小高可用集群3节点Broker组满足多数派机制容忍1节点故障角色动态轮换启动无主从自动选举Leader负责读写所有节点对等配置一致、权限一致、角色动态切换5.3 DLedger对Raft的定制改造核心亮点1、日志模型适配CommitLog原生Raft日志偏向元数据DLedger将Raft日志与RocketMQ CommitLog消息日志打通消息写入即Raft日志写入复用存储结构无双重日志开销。2、优化高吞吐同步机制原生Raft逐条同步性能差DLedger实现批量日志同步、异步刷盘、流水线复制适配MQ百万级高吞吐场景。3、秒级故障转移优化选举超时、心跳检测机制Broker故障后1s内完成重新选举、切换新Leader业务几乎无感知。4、兼容旧版本集群DLedger架构兼容传统主从模式支持平滑升级、无损迁移。5.4 RocketMQ DLedger完整读写流程写流程强一致生产者请求路由至集群Leader节点Leader写入本地CommitLogRaft日志落地Leader批量同步日志至所有Follower节点日志同步至过半节点判定提交成功响应生产者写入成功保证数据不丢读流程高可用消费者可读取Leader、Follower任意节点Follower数据与Leader最终一致分担读压力自动负载均衡提升集群吞吐5.5 DLedger故障自愈流程Leader节点宕机/断网Follower检测心跳超时集群触发新一轮Raft选举快速选出新Leader新Leader接管读写流量集群恢复服务旧Leader重启后自动降级为Follower补齐缺失日志集群恢复三节点完整状态容灾闭环六、传统主从 vs DLedger-Raft 架构对比对比维度传统固定主从架构DLedger-Raft高可用架构节点角色静态固定不可动态切换动态选举自动轮换主从故障转移人工手动切换恢复慢秒级自动选举业务无感知数据一致性异步复制存在数据丢失风险Raft多数派提交强一致不丢数据集群容错Master宕机直接断写容忍少数节点故障高可用极强运维成本高依赖人工运维极低故障自愈、无人值守七、RocketMQ主从节点自动切换完整实现机制源码级核心RocketMQ DLedger集群的主从切换并非简单角色变更而是一套包含心跳检测、超时判定、重新选举、日志对齐、角色切换、流量平滑接管、防双主冲突的完整闭环机制是生产高可用的核心兜底能力。7.1 主从切换核心前置规则触发前提Leader心跳超时、进程宕机、网络分区、节点故障集群约束集群必须过半节点存活才能触发选举、完成主从切换多数派机制切换前置条件新当选节点必须拥有集群最新、最完整的Raft日志杜绝丢数据、脏数据接管防双主机制任期号term全局递增大任期节点自动覆盖小任期节点旧Leader重启自动降级Follower7.2 核心监测机制心跳探测与超时判定DLedger集群默认心跳周期200ms选举超时随机150~300ms规避统一选举冲突。Leader持续向所有Follower发送心跳包同步任期、日志索引、集群状态Follower持续更新最新心跳时间戳一旦Follower超过超时时间未收到心跳判定原Leader已失效触发新一轮选举7.3 完整主从切换执行流程源码执行链路步骤1故障感知状态切换原Leader宕机/断连 → Follower心跳超时 → Follower切换为Candidate候选人term任期号自增1重置选举状态。步骤2全网拉票竞选新LeaderCandidate向集群所有节点发起投票请求投票核心规则只投给任期更新、日志更新的节点同一任期只能投一票获得过半票数直接晋升新Leader步骤3切换前置数据合法性校验关键兜底DLedger在角色切换前强制做两层校验保证数据绝对一致日志完整性校验等待本地ledgerEndIndex committedIndex所有日志完成提交索引转发校验等待ReputMessageService转发完成CommitLog数据完全落地至ConsumeQueue杜绝数据空洞步骤4角色变更、集群状态刷新核心监听类DLedgerRoleChangeHandler感知角色变更执行状态切换新Leader开启读写权限、开启日志同步线程、持续发送心跳、接管集群流量所有Follower停止拉票、被动同步新Leader日志、只提供读服务步骤5旧Leader重启自愈、防双主冲突故障旧Leader恢复上线后发现集群存在更大任期的新Leader自动触发降级逻辑强制放弃Leader身份降级为Follower对比日志差异自动补齐缺失日志、覆盖脏日志最终与集群数据对齐恢复集群三副本完整状态7.4 平滑切换与业务无损保障断写时间极短秒级完成选举切换业务几乎无感知读不中断切换期间Follower可持续提供读能力消费不中断数据零丢失只有日志完整的节点才能当选Leader已提交数据永不回滚杜绝双主任期号全局递增集群永远只有一个最高任期的合法Leader7.5 主从切换核心源码关键点DLedgerLeaderElector核心选举器负责心跳检测、任期管理、投票逻辑、角色切换DLedgerRoleChangeHandler角色变更监听器完成切换后的权限、线程、流量接管reputFromOffset索引转发位点校验保证切换时索引完整无空洞八、RocketMQ BrokerContainer 容器式运行机制很多人疑惑RocketMQ 5.x 为什么要引入BrokerContainer 容器机制核心目的就是解耦、轻量化、模块化、支持多实例隔离、提升集群稳定性彻底改掉旧版Broker大杂烩、耦合严重、启动笨重的问题。8.1 什么是 BrokerContainer可以把BrokerContainer简单理解为Broker的运行容器、统一运行基座。旧版RocketMQ4.x及以前所有功能全部耦合在一个巨大的Broker进程里选主、存储、网络、日志、元数据、同步机制全部堆在一起模块混杂牵一发动全身。新版RocketMQ 5.x用Container容器统一管理所有核心模块把复杂的Broker拆分成一个个独立可插拔的组件容器负责统一加载、启动、调度、销毁实现组件隔离、按需加载、解耦运行。8.2 核心设计思想容器托管一切Broker不再是单一臃肿进程而是由Container统一托管所有核心服务模块模块化拆分将网络服务、存储服务、DLedger选主服务、元数据服务、索引服务拆分为独立组件生命周期统一管理容器统一控制所有模块的初始化、启动、运行、停止、销毁杜绝启动顺序混乱、资源泄露隔离运行各模块资源独立、互不干扰单个模块异常不会直接拖垮整个Broker进程8.3 Container容器承载的核心模块BrokerContainer主要托管四大类核心组件完美适配DLedger-Raft高可用架构网络通信模块Netty服务、请求接收与响应、长连接管理存储核心模块CommitLog、ConsumeQueue、刷盘管理、零拷贝读写DLedger Raft模块心跳检测、节点选举、日志同步、主从切换核心服务辅助功能模块消息重试、死信队列、事务消息、索引转发、元数据管理8.4 容器式运行的核心优势解耦彻底告别旧版代码耦合严重的问题模块各司其职维护性、扩展性大幅提升启动有序可控容器严格控制启动顺序先基础服务、再存储、最后Raft选主避免启动报错、集群状态异常故障隔离单个子模块异常容器可单独回收、重启对应组件不会直接宕机整个Broker适配Raft高可用容器独立托管DLedger服务选主、心跳、日志同步线程独立运行主从切换更稳定、更快速支持多实例、轻量化部署容器基座可复用支持单节点多Broker实例隔离运行适配云原生、容器化部署优雅停机资源回收Broker关闭时容器统一按序停止组件、刷盘、结束Raft集群状态避免数据损坏、日志截断8.5 新旧Broker运行模式对比旧版非容器大一统进程、模块混杂、启动无序、耦合严重、局部异常全局崩溃、适配Raft能力弱新版Container容器式模块化隔离、容器统一调度、启动有序、故障隔离、完美支撑DLedger自动选主与秒级切换8.6 核心总结BrokerContainer就是RocketMQ5.x的Broker运行基座核心作用是模块化解耦、统一生命周期管理、故障隔离为DLedger-Raft高可用集群提供稳定的底层运行环境是RocketMQ云原生、高可用架构升级的重要基础。九、RocketMQ全版本集群架构终极总结RocketMQ集群架构历经三次迭代从静态高可用演进至分布式强一致高可用适配不同业务量级与容灾需求。9.1 架构一单节点架构测试/单机结构单NameServer 单Broker特点部署简单、无高可用、无容错能力适用本地开发、功能测试禁止生产使用9.2 架构二传统固定主从架构4.x早期结构多NameServer集群 固定Master/Slave Broker组写能力仅Master写Slave只读同步模式异步复制/半同步复制故障转移人工手动切换无自动选主优缺点吞吐高、延迟低但存在数据丢失风险、运维成本高、容灾弱适用低重要性业务、非核心链路9.3 架构三DLedger-Raft自动高可用架构4.8/5.x生产主流结构多NameServer 3节点对等Broker Raft集群角色模式无固定主从动态选举Leader/Follower同步模式Raft多数派强一致复制故障转移秒级自动选举、自动切换、故障自愈容错能力容忍单节点永久故障、网络抖动、节点重启优缺点数据强一致、零人工运维、高容灾性能轻微损耗多数派同步适用金融、支付、订单、核心交易等高可靠业务9.4 架构四Controller中心化选主架构5.x全新升级核心升级将选主能力剥离出Broker独立部署Controller集群Raft集群优势减轻Broker计算压力、选主更稳定、集群扩展能力更强、支持大规模集群管理能力统一管理所有Broker组主从切换、故障探测、租约管控彻底杜绝双主问题9.5 RocketMQ集群高可用全景总结NameServer集群高可用多节点部署、无状态、客户端自动路由容错解决路由单点故障Broker存储高可用DLedger-Raft多副本自动主从切换解决存储单点故障与数据丢失问题读写高可用Leader写、多Follower读读写分离、负载均衡提升集群吞吐与稳定性故障自愈高可用故障自动感知、自动选举、自动对齐数据、自动恢复集群完整状态9.6 生产架构最终选型结论普通业务传统主从架构追求极致吞吐、容忍极小概率数据风险核心交易业务DLedger三节点Raft架构优先保障数据一致、故障自愈、业务无损超大规模集群5.x Controller独立选主架构统一管控、稳定可控、扩展性更强十、主从切换集群架构核心问答1、DLedger主从切换核心流程Leader心跳超时 → Follower转Candidate、term自增 → 过半投票选新Leader → 日志索引完整性校验 → 角色切换接管流量 → 旧Leader重启降级对齐数据。2、如何保证切换不丢数据仅日志最新节点可竞选Leader切换前强制校验日志提交完成、索引转发完成已提交日志Raft协议永不回滚。3、如何杜绝双主问题任期号全局递增新Leader任期更大旧Leader感知大任期节点自动降级Follower集群永远唯一合法主节点。4、RocketMQ高可用核心依靠什么NameServer路由集群容错 DLedger-Raft多副本强一致 自动主从故障切换 读写分离负载均衡。5、新旧架构最大差异旧架构角色固定、人工切换、异步复制、存在丢数风险 新架构动态选举、自动自愈、多数派强一致、生产级高可用。