发布订阅就是发布 者产生数据到消息中心,订阅者订阅自己感兴趣的消息,消息中心根据订阅者的订阅情况, 将相关消息或数据发送给对应的订阅者。所以可概括为“送货上门”。 在实际使用场景中,还有一种常用的通信方式,就是将消息或数据放到一个队列里,谁需要 谁就去队列里面取。在分布式领域中,这种模式叫“消息队列”。与发布订阅相比,消息队 列技术的核心思想可以概括为“货物自取”。
队列是一种具有先进先出特点的数据结构,消息队列是基于队列实现的,存储具有特定格式 的消息数据,比如定义一个包含消息类型、标志消息唯一性的 ID、消息内容的一个结构体 作为消息数据的特定格式。消息以特定格式放入这个队列的尾部后可以直接返回,并不需要 系统马上处理,之后会有其他进程从队列头部开始读取消息,按照消息放入的顺序逐一处 理。 从上面的例子中,我们也可以看出引入消息队列的好处是,提高响应速度,以及实现组件间 的解耦。
生产者。生产者会产生消息或数据,并将消息或数据插入到消息队列中。 消息队列。一种具有先进先出特点的数据结构,用于存储消息。 消费者。从消息队列中获取消息或数据,进行相关处理。具体流程是,生产者将发送的消息插入消息队列,也就是入队,之后会有一个消费者从消息 队列中逐次取出消息进行处理,完成出队。
RokcetMQ 共包括 NameServer Cluster、Producer Cluster、Broker Cluster 和 Consumer Cluster 共 4 部分。
NameServer Cluster,指的是名字服务器集群。这个集群的功能与 Kafka 中引入的 ZooKeeper 类似,提供分布式服务的协同和管理功能,在 RocketMQ 中主要是管理 Broker 的信息,包括有哪些 Broker、Broker 的地址和状态等,以方便生产者获取 Broker 信息发布消息,以及订阅者根据 Broker 信息获取消息。
Producer Cluster,指的是生产者集群,负责接收用户数据,然后将数据发布到消息队列 中心 Broker Cluster。集群的好处一是,多个 Producer 可以并发接收用户的输入数据,提升业务处理效率; 二是,考虑到可靠性问题,如果只有一个 Producer 接收用户输入数据,当这个 Producer 故障后,整个业务就无法运行了。
Consumer Cluster,指的是消费者集群,负责从 Broker 中获取消息进行消费。 Consumer 以集群方式进行部署的好处是,提升消费者的消费能力,以避免消息队列中心 存储溢出,消息被丢弃。
Broker Cluster,指的是 Broker 集群,负责存储 Producer Cluster 发布的数据,以方便 消费者进行消费。 Broker Cluster 中的每个 Broker 都进行了主从设计,即每个 Broker 分为 Broker Master 和 Broker Slave,Master 既可以写又可以读,Slave 不可以写只可以读。每次 Broker Master 会把接收到的消息同步给 Broker Slave,以实现数据备份。一旦 Broker Master 崩溃了,就可以切换到 Broker Slave 继续提供服务。这种设计的好处是,提高了系统的可靠性。 可以看出,Broker Cluster 就是“消息队列中心”。
在 Broker Cluster 中,消息的存储采用主题(Topic)+ 消息队列 (Queue)的方式实现。
与 Kafka 一样,RocketMQ 中的主题也是一个逻辑概念。一个主题可以分区,分布在各个 不同的 Broker 中,每个 Broker 上只有该主题的部分数据。每个主题分区中,队列的数量 可以不同,由用户在创建主题时指定。队列是资源分配的基本单元,消息进行存储时会存放 到相应主题的分区中。
以下是RocketMQ的工作流程:
1.首先启动 NameServer,然后启动 Broker。Broker 启动后,会主动找 NameServer 建 立连接,并将自己的信息注册到 NameServer 上。注册完毕后,Broker 会周期性地给 NameServer 发送心跳包,比如每隔 1s 发送一次,以告知 NameServer 自己还活着; 心跳包里还可以包括 Broker 当前存储的数据信息,也就是说 Broker 可以周期性地向 NameServer 更新自己的数据信息,以保证 NameServer 上存储的数据是最新的。
2. 创建主题,并确定这个主题的数据放入哪些 Broker 中。
3.当 Producer 生产消息发送到主题时,需要先到 NameServer 查询该主题存放在哪些 Broker 中,获取到相关 Broker 信息后,将消息发送给这些 Broker 进行存储。
4.Consumer 要从主题消费消息,也需要首先到 NameServer 查询一下该主题的消息存储 在哪些 Broker 上,然后去相应的 Broker 获取消息进行消费。
消息队列模式,是根据消费者需求到消息队列获取数据消费的,消费者只需要知道消息队列 地址即可,消息队列中心也无需提前知道消费者信息。也就是说,这种模式对消费者没有特 别需求,因此比较适合消费者为临时用户的场景。
RocketMQ 应用于购物交易、充值、消息推送等多个场景,因为在 这些场景下,每个消费者不是常驻进程或服务。
发布订阅和消息队列模式虽然都支持系统解耦,但它们在实现时采用的数据结构 和方式并不相同。
发布订阅模式采用了消息中心,消息队列模式采用了消息队列中心,它们均用来存储生 产者发布的数据,并均有主题、Broker 等概念; 唯一不同之处,是消息队列模式中采用了具有先进先出特征的队列结构进行存储,而订 阅发布采用了 map 或数组等方式存储。
消息队列模式中,生产者发布数据到消息队列中心,消息队列中心会存储数据,等待消 费者按需获取数据。这样生产者就不需要和消费者进行直接通信了,实现了生产者和消 费者的解耦。 而在发布订阅模式中,消费者需要提前向消息中心订阅自己感兴趣的数据,待生产者发 布数据到消息中心后,消息中心根据订阅者订阅信息将数据主动推送给消费者,也实现 了消费者和生产者的解耦。 对于消息队列模式,消息队列中心无需提前获取消费者信息,因此对消费者比较灵活,适合 消费者为临时用户的场景;而发布订阅模式,需要消费者提前向消息中心订阅消息,也就是 说消息中心需要提前获取消费者信息,比较适合消费者为长驻进程或服务的场景。