MQ消息队列底层剖析

280 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第20天,点击查看活动详情

1. 消息队列的作用

消息队列是我们最常用的中间件之一,本文不具体针对某一个具体的消息队列,而是从整体概念上建立起我们对于消息队列的基本认识,方便我们后续对RabbitMQ,RocketMQ以及Kafka的针对性学习。

说到消息队列,首先要提的就是其三大基础功能:

  • 解耦:解除生产者与消费者的直接依赖
  • 削峰:将生产者瞬时产生的流量缓缓的释放给消费者
  • 异步:生产者讲消息发送给消息队列之后,可以先异步处理其他的业务,等待返回的信号

例如在秒杀或者是一些其他的业务场景,消息队列对于系统稳定性的提高有很好的作用。

2. 消息队列的模型

消息队列本质上还是一个生产者-消费者模型或者说发布订阅模型,生产者生产消息放入队列,消费者从队列中消费消息。

在消息队列中,我们通常讲上述的过程抽象为以下的组成部分:

image.png

  • producer 是任务的生产方
  • topic 在逻辑上可以被认为是一个queue,但是物理上可以由多个queue组成,每条消息都要有其对应的topic
  • queue 物理意义上的队列数据结构
  • product 消息的生产者
  • consumer 消息的消费者
  • consumer group 消费统一topic的消费者可以组成消费群

3. 消息队列可靠性

前面我们提到了,消息队列能起到解耦、异步等作用,但是,中间件的引入,一定会使系统的复杂度增减,那么,如何保障系统的可靠性就是一个非常重要的命题。

我们可以分为两个部分来思考这个问题:

  1. 保证消息的幂等性,即不被重复消费
    • 为了做到这一点,最保险的方法是在消费端进行消息全局唯一ID的校验,因为很多时候,生产者消息的重复发送是不可避免的。
  2. 保证消息不丢失
    • 生产者发送消息之后,要确保消息队列收到了消息,例如RabbitMQ的confirm机制;
    • 消息队列在确保消费者在成功消费掉消息以后,再删除消息,例如RabbitMQ的ack机制;

4. 死信队列与延时队列

  • 死信队列用来处理没有被成功消费的消息
  • 延时队列用来处理定时一段时间后需要处理的消息