分布式通信:消息队列


前言

发布订阅是发布者产生数据到消息中心,订阅者订阅自己感兴趣的消息,消息中心根据订阅者的订阅情况, 将相关消息或数据发送给对应的订阅者。

在实际使用场景中,还有一种常用的通信方式,是将消息或数据放到一个队列里,谁需要谁就去队列里面取。在分布式领域中,这种模式叫“消息队列”。

什么是消息队列?

电子论文订阅的例子中,出版社或会议方将论文发布到论文网站 (或平台)上,然后论文网站再将论文推送给订阅相关论文的老师或学生。这里的论文网站就是消息中心,负责根据订阅信息将论文送货上门,角色非常关键。

除了将论文送货上门外,还有另外一种模式,是出版社或会议方将论文发布到论文网站进行存储,老师或学生根据需要到论文网站按需购买文章。 这种思想,在分布式通信领域中称为消息队列模式,论文网站充当的就是消息队列的角色。

比如,很多系统都提供了用户注册功能,注册完成后发送通知邮件。如下图所示,假设用户通过邮箱进行注册,填写完注册信息并点击提交后,系统的处理过程主要分为两步:

  1. 检查用户注册信息的合法性,如果合法则将注册信息写入数据库中,若不合法,直接返回,流程结束;
  2. 将用户注册信息写入数据库后,给用户发送通知邮件,以告知用户注册的相关信息,比如注册账号等信息。

假设系统将注册信息写入数据库需要花费 400ms、给用户发送通知邮件需要花费 600ms。

在这里插入图片描述

这时,注册消息写入数据库和发送通知邮件这两个组件间是直接交互,且是同步通信方式。 那么从用户提交注册到收到响应,需要等系统完成这两个步骤。如果不考虑通信延迟的话,注册系统对用户的响应时间是 1000ms,即 1s。

如下图所示,如果引入消息队列作为注册消息写入数据库和发送通知邮件这两个组件间的中间通信者,那么这两个组件就可以实现异步通信、异步执行。引入消息队列后,上述步骤可以分为三步:

  1. 检查用户注册信息的合法性,如果合法则将注册信息写入数据库中,若不合法则直接返回,流程结束;
  2. 注册消息写入消息数据库后,将消息写入消息队列的队尾;
  3. 发送通知邮件的组件去消息队列取出队首的消息,给用户发送通知邮件,告知用户注册的相关信息。

采用消息队列模式,只需要第 2 步完成,即可给用户返回响应。第 3 步发送通知邮件可以在返回响应之后执行。

用户的注册信息写入数据库之后,通过数据库的可靠性设计来保证用户注册信息不会丢失, 发送通知邮件的组件一定可以获取到用户注册信息,即保证会给注册用户发送通知邮件。消息队列的引入不会影响用户注册网站,但会提升用户响应效率。

在这里插入图片描述

通常情况下,将消息写入消息队列的速度很快,假设需要 100ms。引入消息队列后,发送通知邮件实现了异步读取,系统响应时间缩短为 500ms,响应速度提升了一倍, 提升了用户体验。

队列是一种具有先进先出特点的数据结构,消息队列是基于队列实现的,存储具有特定格式的消息数据,比如定义一个包含消息类型、标志消息唯一性的 ID、消息内容的一个结构体作为消息数据的特定格式。消息以特定格式放入这个队列的尾部后可以直接返回,并不需要系统马上处理,之后会有其他进程从队列头部开始读取消息,按照消息放入的顺序逐一处理。 引入消息队列的好处是,提高响应速度,以及实现组件间的解耦。

消息队列工作原理

消息队列的核心结构,如下图所示。与发布订阅模式类似,消息队列模式也是包括 3 个核心部分:

  • 生产者。产生消息或数据,并将消息或数据插入到消息队列中。
  • 消息队列。先进先出特点的数据结构,用于存储消息。
  • 消费者。从消息队列中获取消息或数据,进行相关处理。

生产者将发送的消息插入消息队列,也就是入队,之后会有一个消费者从消息队列中逐次取出消息进行处理,完成出队。

在这里插入图片描述

RocketMQ 消息队列原理及工作机制

RocketMQ 的架构图:

在这里插入图片描述
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 应用于购物交易、充值、消息推送等多个场景,因为在这些场景下,每个消费者不是常驻进程或服务,几乎都是临时存在。此外,滴滴、联想等公司也都有采用 RocketMQ。

知识扩展:发布订阅和消息队列模式都支持系统解耦,两者是否一致呢?

发布订阅和消息队列模式虽然都支持系统解耦,但它们在实现时采用的数据结构和方式并不相同。

数据结构不同:

发布订阅模式采用了消息中心,消息队列模式采用了消息队列中心,它们均用来存储生产者发布的数据,并均有主题、Broker 等概念;
唯一不同之处,是消息队列模式中采用了具有先进先出特征的队列结构进行存储,而订阅发布采用了 map 或数组等方式存储。

实现解耦的方式不同:

消息队列模式中,生产者发布数据到消息队列中心,消息队列中心会存储数据,等待消费者按需获取数据。这样生产者就不需要和消费者进行直接通信了,实现了生产者和消费者的解耦。

在发布订阅模式中,消费者需要提前向消息中心订阅自己感兴趣的数据,待生产者发布数据到消息中心后,消息中心根据订阅者订阅信息将数据主动推送给消费者,也实现了消费者和生产者的解耦。

消息队列模式,消息队列中心无需提前获取消费者信息,因此对消费者比较灵活,适合消费者为临时用户的场景;

发布订阅模式,需要消费者提前向消息中心订阅消息,消息中心需要提前获取消费者信息,比较适合消费者为长驻进程或服务的场景。

总结

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海陆云

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值