什么是消息队列?
消息队列,一般我们会简称它为MQ(Message Queue),嗯,就是很直白的简写。
我们先不管消息(Message)这个词,来看看队列(Queue)。队列是一种先进先出的数据结构。如下图
消息(Message)可以认为是一个打包好的数据。
消息队列可以简单理解为:把要传输的数据放在队列中。如下图:
为什么要用消息队列?
应用解耦、逻辑异步、并发削峰
应用解耦
传统模式:
传统模式的缺点:系统间耦合性太强,如上图所示,系统A在代码中直接调用系统B和系统C的代码,如果将来D系统接入,系统A还需要修改代码,过于麻烦!
中间件模式:
中间件模式的的优点:
将消息写入消息队列,需要消息的系统自己从消息队列中订阅,从而系统A不需要做任何修改。
逻辑异步
传统模式:
传统模式的缺点:
一些非必要的业务逻辑以同步的方式运行,太耗费时间。
中间件模式:
中间件模式的的优点:
将消息写入消息队列,非必要的业务逻辑以异步的方式运行,加快响应速度
并发削峰
传统模式:
传统模式的缺点:
并发量大的时候,所有的请求直接怼到数据库,造成数据库连接异常.
中间件模式:
中间件模式的的优点:
系统A慢慢的按照数据库能处理的并发量,从消息队列中慢慢拉取消息。在生产中,这个短暂的高峰期积压是允许的。
消息队列的一些基本概念和简单原理
把数据放到消息队列里叫做生产者。
从消息队列里边取数据叫做消费者。
我们可以把消息队列比作是一个存放消息的容器。
Broker
Broker的概念来自与Apache ActiveMQ,通俗的讲就是MQ的服务器。
点对点消息队列模型
点对点模式下包括三个角色:
消息队列
发送者 (生产者)
接收者 (消费者)
消息发送者生产消息发送到queue中,然后消息接收者从queue中取出并且消费消息。消息被消费以后,queue中不再有存储,所以消息接收者不可能消费到已经被消费的消息。每一个成功处理的消息都由消息消费者签收确认(Acknowledge)。如图:
点对点模式特点:
每个消息只有一个接收者(Consumer)(即一旦被消费,消息就不再在消息队列中);
发送者和接收者间没有依赖性,发送者发送消息之后,不管有没有接收者在运行,都不会影响到发送者下次发送消息;
接收者在成功接收消息之后需向队列应答成功,以便消息队列删除当前接收的消息;
发布/订阅模型
发布/订阅模式下包括三个角色:
角色主题(Topic)
发布者(Publisher)
订阅者(Subscriber)
发布订阅模型中,支持向一个特定的Topic发布消息。订阅者们可以订阅特定的Topic,订阅后的订阅者可以接收到消息。
发布/订阅模式特点:
每个消息可以有多个订阅者;
发布者和订阅者之间有时间上的依赖性。针对某个主题(Topic)的订阅者,它必须创建一个订阅者之后,才能消费发布者的消息。
为了消费消息,订阅者需要提前订阅该角色主题,并保持在线运行;
消息的顺序性保证
基于Queue消息模型,利用FIFO先进先出的特性,可以保证消息的顺序性。
消息的ACK机制
即消息的Ackownledge确认机制,为了保证消息不丢失,消息队列提供了消息Acknowledge机制,即ACK机制,当Consumer确认消息已经被消费处理,发送一个ACK给消息队列,此时消息队列便可以删除这个消息了。
如果Consumer宕机/关闭,没有发送ACK,消息队列将认为这个消息没有被处理,会将这个消息重新发送给其他的Consumer重新消费处理。
消息的持久化
消息的持久化,对于一些关键的核心业务来说是非常重要的,启用消息持久化后,消息队列宕机重启后,消息可以从持久化存储恢复,消息不丢失,可以继续消费处理。
消息的同步和异步收发
同步:消息的收发支持同步收发的方式。
同时还有另一种同步方式:同步收发场景下,消息生产者和消费者双向应答模式,例如:张三写封信送到邮局中转站,然后李四从中转站获得信,然后在写一份回执信,放到中转站,然后张三去取,当然张三写信的时候就得写明回信地址。
消息的接收如果以同步的方式(Pull)进行接收,如果队列中为空,此时接收将处于同步阻塞状态,会一直等待,直到消息的到达。
异步:消息的收发同样支持异步方式:异步发送消息,不需要等待消息队列的接收确认;异步接收消息,以Push的方式触发消息消费者接收消息。
消息的事务支持
消息的收发处理支持事务,例如:在任务中心场景中,一次处理可能涉及多个消息的接收、处理,这处于同一个事务范围内,如果一个消息处理失败,事务回滚,消息重新回到队列中。
使用消息队列有什么问题?
系统可用性降低:你想啊,本来其他系统只要运行好好的,那你的系统就是正常的。现在你非要加个消息队列进去,那消息队列挂了,你的系统不是呵呵了。因此,系统可用性降低了。
系统复杂性增加:要多考虑很多方面的问题,比如一致性问题、如何保证消息不被重复消费,如何保证保证消息可靠传输。因此,需要考虑的东西更多,系统复杂性增大。
本文回顾:
什么是消息队列?
为什么要用消息队列?
消息队列的一些基本概念和简单原理
使用消息队列有什么问题?