RocketMQ架构原理

RocketMQ架构原理 集群部署架构结合部署结构图描述集群工作流程1启动NamesrvNamesrv起来后监听端口等待Broker、Produer、Consumer连上来相当于一个路由控制中心。2Broker启动跟所有的Namesrv保持长连接定时发送心跳包。心跳包中包含当前Broker信息(IP端口等)以及存储所有topic信息。注册成功后namesrv集群中就有Topic跟Broker的映射关系。3收发消息前先创建topic创建topic时需要指定该topic要存储在哪些Broker上。也可以在发送消息时自动创建Topic。4Producer发送消息启动时先跟Namesrv集群中的其中一台建立长连接并从Namesrv中获取当前发送的Topic存在哪些Broker上然后跟对应的Broker建长连接直接向Broker发消息。5Consumer跟Producer类似。跟其中一台Namesrv建立长连接获取当前订阅Topic存在哪些Broker然后直接跟Broker建立连接通道开始消费消息。模块功能特性Namesrv就是一个注册中心存储当前集群所有Brokers信息、Topic跟Broker的对应关系。Namesrv用于存储Topic、Broker关系信息功能简单稳定性高。多个Namesrv之间相互没有通信单台Namesrv宕机不影响其他Namesrv与集群即使整个Namesrv集群宕机已经正常工作的ProducerConsumerBroker仍然能正常工作但新起的Producer, ConsumerBroker就无法工作。Namesrv压力不会太大平时主要开销是在维持心跳和提供Topic-Broker的关系数据。但有一点需要注意Broker向Namesr发心跳时会带上当前自己所负责的所有Topic信息如果Topic个数太多万级别会导致一次心跳中就Topic的数据就几十M网络情况差的话网络传输失败心跳失败导致Namesrv误认为Broker心跳失败。nameserver是rocketmq自己实现的配置服务器不是Zookeeper。Broker集群最核心模块主要负责Topic消息存储、管理和分发等功能。1高并发读写服务Broker的高并发读写主要是依靠以下两点消息顺序写每台borker上所有Topic数据同时只会写一个文件一个文件满1G再写新文件真正的顺序写盘使得发消息TPS大幅提高。消息随机读RocketMQ尽可能让读命中系统pagecache因为操作系统访问pagecache时即使只访问1K的消息系统也会提前预读出更多的数据在下次读时就可能命中pagecache减少IO操作。2负载均衡与动态伸缩负载均衡Broker上存Topic信息Topic由多个队列组成队列会平均分散在多个Broker上而Producer的发送机制保证消息尽量平均分布到所有队列中最终效果就是所有消息都平均落在每个Broker上。动态伸缩能力非顺序消息Broker的伸缩性体现在两个维度Topic, Broker。Topic维度假如一个Topic的消息量特别大但集群水位压力还是很低就可以扩大该Topic的队列数Topic的队列数跟发送、消费速度成正比。Broker维度如果集群水位很高了需要扩容直接加机器部署Broker就可以。Broker起来后向Namesrv注册Producer、Consumer通过Namesrv发现新Broker立即跟该Broker直连收发消息。3高可用高可靠高可用集群部署时一般都为主备备机实时从主机同步消息如果其中一个主机宕机备机提供消费服务但不提供写服务。高可靠所有发往broker的消息有同步刷盘和异步刷盘机制同步刷盘时消息写入物理文件才会返回成功异步刷盘时只有机器宕机才会产生消息丢失broker挂掉可能会发生但是机器宕机崩溃是很少发生的除非突然断电4Broker与Namesrv的心跳机制单个Broker跟所有Namesrv保持心跳请求心跳间隔为30秒心跳请求中包括当前Broker所有的Topic信息。Namesrv会反查Broer的心跳信息如果某个Broker在2分钟之内都没有心跳则认为该Broker下线调整Topic跟Broker的对应关系。但此时Namesrv不会主动通知Producer、Consumer有Broker宕机。消费者Consumer消费者启动时需要指定Namesrv地址与其中一个Namesrv建立长连接。消费者每隔30秒从nameserver获取所有topic的最新队列情况这意味着某个broker如果宕机客户端最多要30秒才能感知。连接建立后从namesrv中获取当前消费Topic所涉及的Broker直连Broker。Consumer跟Broker是长连接会每隔30秒发心跳信息到Broker。Broker端每10秒检查一次当前存活的Consumer若发现某个Consumer 2分钟内没有心跳就断开与该Consumer的连接并且向该消费组的其他实例发送通知触发该消费者集群的负载均衡。消费者端的负载均衡先讨论消费者的消费模式消费者有两种模式消费集群消费广播消费。广播消费每个消费者消费Topic下的所有队列。集群消费一个topic可以由同一个ID下所有消费者分担消费。具体例子假如TopicA有6个队列某个消费者ID起了2个消费者实例那么每个消费者负责消费3个队列。如果再增加一个消费者ID相同消费者实例即当前共有3个消费者同时消费6个队列那每个消费者负责2个队列的消费。消费者端的负载均衡就是集群消费模式下同一个ID的所有消费者实例平均消费该Topic的所有队列。但是Consumer 数量要小于等于队列数量如果Consumer 超过队列数量那么多余的Consumer 将不能消费消息。生产者(Producer)Producer启动时也需要指定Namesrv的地址从Namesrv集群中选一台建立长连接。如果该Namesrv宕机会自动连其他Namesrv。直到有可用的Namesrv为止。生产者每30秒从Namesrv获取Topic跟Broker的映射关系更新到本地内存中。再跟Topic涉及的所有Broker建立长连接每隔30秒发一次心跳。在Broker端也会每10秒扫描一次当前注册的Producer如果发现某个Producer超过2分钟都没有发心跳则断开连接。生产者端的负载均衡生产者发送时会自动轮询当前所有可发送的broker一条消息发送成功下次换另外一个broker发送以达到消息平均落到所有的broker上。这里需要注意一点假如某个Broker宕机意味生产者最长需要30秒才能感知到。在这期间会向宕机的Broker发送消息。当一条消息发送到某个Broker失败后会往该broker自动再重发2次假如还是发送失败则抛出发送失败异常。业务捕获异常重新发送即可。客户端里会自动轮询另外一个Broker重新发送这个对于用户是透明的。