RocketMQ是一个分布式消息中间件,主要包含了4个模块:
NameServer:管理集群里所有Broker的信息,让使用MQ的系统可以通过他感知到集群里有哪些Broker。
Broker:集群最核心模块,主要负责Topic消息存储、消费者的消费位点管理(消费进度)。
Product:消息生产者,每个生产者都有一个ID(编号),多个生产者实例可以共用同一个ID。同一个ID下所有实例组成一个生产者集群。
Consumer:消息消费者,每个订阅者也有一个ID(编号),多个消费者实例可以共用同一个ID。同一个ID下所有实例组成一个消费者集群。
NameServer
我们已经知道NameServer是用来维护Broker信息的,那么为了避免单点故障,NameServer生产环境下一定是集群部署。不过多个NameServer之间相互没有通信、它们都有完整的信息,单台NameServer宕机不影响集群其他节点。NameServer压力不会太大,平时主要开销是在维持心跳和提供Topic-Broker的关系数据。
Broker
Broker在启动的时候,就会把自己的信息注册到所有NameServer中去,然后每一台NameServer都知道集群里有这么一台Broker的存在了。Broker和NameServer之间会有一个心跳机制,Broker每30s给所有NameServer发送心跳、告诉自己还活着;然后NameServer每10s会检查一次Broker和自己最近一次的心跳时间,如果120s内都没发现broker的心跳信息,则认为broker挂掉了。
同样的,Broker为了保证高可用肯定也要采用集群架构,Slave-Broker采用pull的模式拉取Master-Broker的消息。生产者发消息是发给Master-Broker,消费者读消息可能是Master-Broker也可能是Slave-Broker。(Master Broker会根据自身负载建议你是否去从Slave Broker去读取消息)。不过早期的版本里,master挂了不会自动切换到slave里面去;在RocketMQ4.5后引入了Dledger机制,通过Raft协议实现了自动切换,不过Dledger要求一个master至少要有2个slave,这样三个broker组成一个group。
Consumer/Producer
而生产者和消费者则采用pull+长轮询的方式,主动去NameServer上拉取Broker信息,这样既通过长轮询达到了push的实时性,又有了pull的可控性。
Topic
Topic用于将消息按主题做划分,Producer将消息发往broker中指定的Topic,Consumer订阅该Topic就可以收到这条消息。Topic跟发送方和消费方都没有强关联关系,发送方可以同时往多个Topic投放消息,消费方也可以订阅多个Topic的消息。在RocketMQ中,Topic是一个上逻辑概念。消息存储不会按Topic分开。举个例子,现在你的订单系统需要往MQ里发送订单消息,那么此时你就应该建一个Topic,他的名字可以叫做:topic_order_info,也就是一个包含了订单信息的数据集合。要是你有一些商品数据要发送消息到MQ里,你就应该创建一个Topic叫做“topic_product_info”,代表里面都是商品数据,那些想要从MQ里获取商品数据的系统就可以从“topic_product_info”里获取了。