消息队列基础

119 阅读4分钟

消息队列基础

消息队列,即Message Queue,简称MQ

是什么

就是一个用于服务间通信的中间件,包含生产者和消费者两个角色,生产者向队列生产消息,消费者从队列消费消息,从而实现了通信。

有什么用

主要用途:

  1. 解耦
  2. 异步
  3. 削峰

解耦

生产中可能有如下痛点:系统内上下游服务直接耦合,扩展难、维护难。


举例:

a、d是上游服务,b、c、e是下游服务

不使用消息队列时系统架构如下:

微信图片_20220702115324.jpg

接口调用,上游服务调用下游服务接口

痛点:

增加了新的下游服务下游服务提供的接口发生变动,则上游a、d就必须修改代码


使用消息队列时系统架构如下:

微信图片_20220702115340.jpg

即上游服务生产消息,下游服务消费消息、执行逻辑处理

此时,再新增下游服务或下游服务接口有变动,不会影响到上游a、d,上游服务只管生产消息,而下游服务消费消息、执行逻辑处理即可,上下游通过MQ解耦。

异步

生产中可能有如下痛点

接口的调用链路很长,可能需要调用非常多的服务,若同步调用,则接口响应慢,用户体验不好,且会降低系统的吞吐量。


场景举例:

一个用户的下单操作,会经过如下链路:

  1. 调用订单服务,更新订单状态
  2. 调用库存服务,扣减库存
  3. 调用消息服务,发送消息触达用户
  4. 调用积分服务,增加用户积分
  5. ...

可以看到调用链路很长,如果同步调用,则用户的下单操作响应会很慢,另外用户下单时核心业务逻辑就是更新订单的状态,其他操作不需要同步且实时性要求没那么高,完全可以异步执行,此时就可以使用消息队列实现异步处理:

订单服务处理完订单状态后,向消息队列发送一个消息,然后直接返回;库存服务、消息服务、积分服务等下游服务分别消费消息、执行相应的逻辑处理

640.png

削峰

生产中有如下痛点

某时间段服务的访问量非常高,远大于服务集群的处理能力,可能会打挂服务


可以把请求扔到消息队列里,服务从消息队列中取出请求进行处理,有消息队列在前面缓冲,就避免了大流量打挂服务。

640-16567399428204.png

其他应用场景

  • 数据采集,比如,收集业务日志监控数据用户行为等数据。

一定要使用消息队列吗

使用消息队列有好处,也有坏处,好处如上所述,坏处有

  1. 系统可用性降低。使用了消息队列,系统就会增加依赖,若消息队列挂了,可能导致系统不可用
  2. 系统复杂度增加。使用了消息队列,需要考虑额外的问题,比如:消息丢失、消息重复、消息堆积、消费失败等问题。

主流的几种MQ

640-16567433070277.png

MQ协议

  • JMS
  • AMQP
  • STOMP
  • MQTT

不是所有的MQ产品都会实现以上协议,有些是自定义协议

消息队列的数据流图

微信图片_20220702115358.jpg

在大多数MQ产品中,存储消息的服务器叫做broker,说白了就是消息队列服务端

消息模型

  • 点对点模型
  • 发布/订阅模型

点对点模型

微信图片_20220702115346.jpg

一个消息只能由一个消费者消费。

缺点:不能满足多个消费者都消费全量消息的需求。

发布/订阅模型

微信图片_20220702115353.jpg

在发布/订阅模型中:

一个消息必须属于一个topic,topic对消息进行分类;

生产者就是发布者,向topic发布消息;

消费者就是订阅者,订阅topic,从而消费topic的消息;

topic的每个订阅者都能消费该topic的全量消息

优点:

能满足多个消费者都消费全量消息的需求。

消费模式

消费模式是消费者获取消息的方式,有:

  1. push模式:MQ主动给消费者推消息
  2. pull模式:消费者主动从MQ拉消息(会轮询)

对比:

  • push模式:

    • 优点:实时性好。

    • 缺点:

      1. 若生产者生产速度快于消费者消费速度,则消费者会来不及消费,导致消费者进程内存占满,甚至崩溃
      2. 因为是MQ主动,所以MQ的负担较重
      3. 无反馈机制,无法知道消息是否消费成功。
  • pull模式:

    • 优点:

      1. 消费者可以控制消费速度
      2. MQ的负担轻
      3. 有反馈,若消息消费失败会重新入队
    • 缺点:实时性不行。

消息队列常见的一些问题

  1. 消息丢失
  2. 消息重复
  3. 消费失败,重试消费
  4. 消息堆积

后续详细介绍