RocketMQ架构原理八股面试
架构原理RocketMQ 整体架构流程简述生产者→NameServer→Broker→消费者每个Broker在创建好后会向所有NameServer汇报自己的Topic路由信息即 Broker地址、Topic配置、都写队列路由信息每个NameServer都会以Topic为分类整理Broker汇报的路由信息。客户端Productor/Consumer会定时从NameServer获取路由信息来更新本地Topic下的Broker信息如果某一个Broker访问失败则会重新查询NameServer更新路由信息。以上整个链路搭建完成。Productor根据路由Topic信息选择一个WriteMessageQueue将消息发送到对应BrokerBroker收到消息后写入CommitLog再根据CommitLog构键ConsumerQueue和IndexFile完成持久化。ConsumerGroup下的每个Consumer会根据Rebalance分配到若干个ReadMessageQueue从Broker拉取消息进行消费。消费成功后向Broker提交消费结构更新消费点位确认该消息为正常消费。若消费失败则会重试每一次重试的间隔时间都会更长直到16次重试机会全部耗尽则会加入死信队列DLQ待人工处理后补偿消费。NameServer 为什么设计成无状态RocketMQ的NameServer采用无状态而非Raft、Paxos、Zookeeper那样的主从选举是因为NameServer只是缓存Broker的信息而Broker真正的信息在他们各自的手中所以RocketMQ没有采用中心化思想要求所有NameServer都要确保Broker数据的强一致性而是分为主动和被动两种方案尽可能维护NameServer中缓存的Broker信息的正确性。主动Broker每间隔30秒默认向所有NameServer发送 路由注册 心跳请求 来更新NameServer中缓存的Broker信息。而客户端Productor/Consumer并不是一直使用首次从某一NameServer查询到的Broker信息一直使用默认10秒会清空客户端的Broker缓存信息重新轮询查询其他NameServer来更新客户端的Broker缓存信息。被动Productor/Consumer在与NameServer中查询到的Broker进行连接发送消息时若是出现了失败Productor/Consumer还是会轮询其他NameServer查询Broker信息更新到本地客户端至于先前缓存不一致的NameServer则会由 30秒间隔的 路由注册 心跳请求来更新。RocketMQ权衡了引入Raft、Paxos、Zookeeper带来的复杂度 和 NameServer最终一致性的设计会造成的短时间内Broker使用不均衡 最后仍然决定使用后者认为短时间内的Broker使用不均衡在后续NamerServer更新完缓存的Broker信息最终仍然可以较为均衡的使用所有Broker而额外算法的引入则会大大增加维护和开发难度。Broker 如何同步 Topic 路由信息RokcetMQ不会同步路由消息而是每个Broker维护自身的Topic配置并在启动及运行期间通过registerBroker定期向所有NameServer上报自己的Topic配置信息再由各个NameServer统一汇总整理每个Topic下的Broker。后续客户端即可定时从NameServer查询指定Topic路由消息并且缓存在客户端本地。RocketMQ 队列机制Topic 默认多少队列读写队列区别Productor发布的消息并不是直接发送到Topic下。而是Topic下的MessageQueue一个Topic默认创建4个MessageQueue分别为4个读队列和4个写队列即一个队列分别有读写功能而非8个队列4个读队列和4个写队列。Productor发布消息到指定Topic-Broker下的写队列Consumer读取指定Topic-Broker下的读队列消息进行消费。若指定创建8个写队列4个读队列则会创建8个队列着8个队列全都有写功能但只有其中4个有读功能。即 QueueNumsmax(readQueueNums.writeQueueNums).