1、什么是消息队列
消息队列就是存储消息的队列。队列有一个显著特点,那就是"先进先出"。就像我们在食堂排队打饭一样,排在前面的人先打饭,这正是队列最常见的特点。
假设这是一个消息队列,它可以存储消息。那么这就引出了我们的核心概念,即消息的存储。其中涉及到三个关键词:存储、队列和消息。
消息:可以将“消息”理解为某种数据结构,例如字符串、对象、二进制数据或 Json 数据等。
1、消息队列与分享接口的区别
消息队列与分享接口的主要区别在于,消息队列可以存储数据,而分享接口,像 HTTP 请求一样,发送完之后就没有了,它不会帮你保存数据。
2、消息队列与数据库的不同
消息队列和数据库的最大区别在于其应用场景和作用。消息队列不仅可以实现消息的传输,而且可以在多个不同的系统应用之间实现消息的传输,无需关心应用的编程语言或系统框架。例如,你可以让 Java 开发的应用发送消息,让 PHP 开发的应用来接收消息。这样,我们就不需要把所有的代码都写在一个系统或项目里,实现了所谓的应用解耦。
2、消息队列的模型
消息队列主要由四部分组成:消息生产者(Producer)、消息消费者(Consumer)、消息(Message)和消息队列(Queue)。这里,我们可以通过一个类比来理解消息队列的运作方式。
场景描述:小王是一个快递员(消息生产者),他在早上八点拿到了一个包裹(消息)。然而,收件人小李(消息消费者)说早上八点他有事,无法收快递,让小王晚上八点再来送。此时,如果有一个快递柜(消息队列),小王就可以将包裹存放在快递柜里,然后告诉小李密码,小李什么时候有时间就可以去取包裹。在这个过程中,小王并不需要等小李在家 。
角色 | 在消息队列中代表什么 |
---|---|
小王(快递员) | 消息生产者(Producer)——负责产生消息并发出去 |
小李(收件人) | 消息消费者(Consumer)——负责接收并处理消息 |
快递柜 | 消息队列(Message Queue)——临时存放消息的地方 |
包裹 | 消息(Message)——需要被传递和处理的数据 |
这个例子很好说明了消息队列的特点:
- 解耦:生产者和消费者不直接联系,不用关心对方在不在、忙不忙。
- 异步:生产者先完成自己的任务,消费者啥时候取都行。
- 可靠传递:快递柜确保包裹不会丢(MQ 确保消息不丢、不重发)。
- 削峰填谷:如果小王一次送 100个包裹,小受也可以慢慢取,不怕被瞬间挤爆。
3、消息队列优势总结
1、异步处理:一旦生产者发送完消息,便可以立即转向其他任务,而消费者则可以在任何时候开始处理消息。这样一来,生产者和消费者之间就不会发生阻塞。
2、削峰填谷:消息队列允许我们先将用户请求存储起来,然后消费者(或说实际执行任务的应用)可以根据自身的处理能力和需求,逐步从队列中取出并处理请求。
4、分布式消息队列的优势
1、应用解耦
在没有消息队列之前,假设我们有一个订单系统,库存系统和发货系统。以往,我们将所有这些系统全都放到同一个大项目中,它需要调用库存系统进行减库存,然后又要调用发货系统进行发货。这会带了一个问题,如果库存系统调用成功,但发货系统突然调用失败,整个系统就会出现问题。如果发货系统崩溃,库存系统可能也会受到影响。
但如果我们实施应用解耦,订单系统下订单时只需向消息队列发送一个消息,然后立即返回。库存系统和发货系统可以从消息队列中取出消息进行处理。如果发货系统突然宕机,也不会影响库存系统。当发货系统恢复后,可以从消息队列中找到订单消息,然后继续执行业务逻辑。
通过消息队列,订单系统不需要同步调用所有系统,只需发送消息到队列就可以立即返回,这样性能更高,响应时间更短。这就是为什么我们在构建秒杀系统时,必须要用消息队列,你可以将所有耗时的操作全部推给消息队列,让库存和发货系统自己去处理订单,它们可以自己去保证订单不被重复执行等。
2、发布订阅模式
我们常在公司中遇到这样的场景:假设你在一家大公司,以腾讯为例,我们都知道,腾讯有许多产品,许多产品都需要用 QQ 号登录。如果 QQ 对其账号体系进行了改革,那么所有使用 QQ 号登录的下游系统都必须知道这个变化。
现在设想这样一个场景,腾讯有非常多的子系统,例如微信、王者荣耀等,假设有 100 个这样的系统。如果 QQ 进行了一些改革,我们如何将这些改变通知给这些系统?最简单,但也最费时的方法,就是直接一个个通知。例如,QQ 发布了新的数据或进行了一些调整,需要让其他系统知道,或者 QQ 发布了新的公告,其他系统也需要同步这个公告。
但这会有一个问题,系统越多,这个操作的时间就会越长,而且可能会遇到失败的情况。其次,假设现在有100 个系统,如果有新的项目或团队加入,他们可能不知道要接收 QQ 的这些变动,而且 QQ 也无法得知新加入的项目,因此可能会有信息漏洞,这是致命的。
解决方案:大的核心系统(如 QQ)向一个地方,也就是我们的消息队列发送消息,然后其他的系统都去订阅这个消息队列,读取这个消息队列中的消息就可以了。这样,QQ 就不需要关心背后有多少系统,只需要向消息队列发送消息,其他系统如果需要这些消息,就可以从消息队列中获取,这样就解决了上述的问题。
5、消息队列的应用场景
- 耗时的场景(异步)
- 高并发场景(异步、削峰填谷)
- 分布式系统协作(尤其是跨团队、跨业务协作,应用解耦)
- 强稳定性的场景(比如金融业务,持久化、可靠性、削峰填谷)