MQ(Message Queue)消息队列,是基础数据结构中“先进先出”的一种数据机构。指把要传输的数据(消息)放在队列中,用队列机制来实现消息传递——生产者产生消息并把消息放入队列,然后由消费者去处理。消费者可以到指定队列拉取消息,或者订阅相应的队列,由MQ服务端给其推送消息。
MQ的作用
消息队列中间件是分布式系统中重要的组件,主要解决应用解耦,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性架构。
解耦:一个业务需要多个模块共同实现,或者一条消息有多个系统需要对应处理,只需要主业务完成以后,发送一条MQ,其余模块消费MQ消息,即可实现业务,降低模块之间的耦合。
异步:主业务执行结束后从属业务通过MQ,异步执行,减低业务的响应时间,提高用户体验。
削峰:高并发情况下,业务异步处理,提供高峰期业务处理能力,避免系统瘫痪。
MQ的缺点
1、系统可用性降低。依赖服务越多,服务越容易挂掉。需要考虑MQ瘫痪的情况
2、系统复杂性提高。需要考虑消息丢失、消息重复消费、消息传递的顺序性
3、业务一致性。主业务和从属业务一致性的处理
主要的MQ产品
主要的MQ产品包括:RabbitMQ、ActiveMQ、RocketMQ、ZeroMQ、Kafka、IBM WebSphere 等。
常用的两种消息队列组件
RabbitMQ:高可用、高可靠消息应用场景,例如记账失败重试、通知服务,消息不允许丢
Kafka:高性能消息应用场景,例如日志、监控,消息允许丢失。
1、消息队列的基本概念
MQ拥有先进先出(First input First Output,FIFO)的特性,能把要传输的数据(消息)放在队列中,用队列机制来实现消息传递——生产者产生消息并把消息放入队列,然后由消费者去处理。消费者可以到指定队列拉取消息,或者订阅相应的队列,由MQ服务端给其推送消息。
1.1、Broker(经纪人; 掮客)
Broker的概念来自与Apache ActiveMQ,通俗的讲就是MQ的服务器。
1.2、消息的生产者、消费者
消息生产者Producer:发送消息到消息队列。
消息消费者Consumer:从消息队列接收消息。
2、点对点模式
一对一,消费者主动拉取数据,消息收到后消息清除
点对点消息队列模型通常是一个基于拉取或者轮询的消息传送模型,这种模型从队列中请求信息,而不是将消息推送到客户端。这个模型的特点是发送到队列的消息被一个且只有一个接收者接收处理,即使有多个消息监听者也是如此。
3、发布/订阅模式(Topic)
一对多,数据生产后,推送给所有订阅者
发布订阅消息模型则是一个基于推送的消息传送模型。发布订阅模型可以有多种不同的订阅者,临时订阅者只在主动监听主题时才接收消息,而持久订阅者则监听主题的所有消息,即使当前订阅者不可用,处于离线状态。
发布订阅消息模型中,支持向一个特定的主题Topic发布消息,0个或多个订阅者接收来自这个消息主题的消息。在这种模型下,发布者和订阅者彼此不知道对方。实际操作过程中,必须先订阅,再发送消息,而后接收订阅的消息,这个顺序必须保证。
4、消息队列的主要作用
最重要的作用:
异步
解耦
削峰
4.1、解耦
允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束。
4.2、冗余
消息队列把数据进行持久化直到它们已经被完全处理,就是消息的持久化,通过这一方式规避了数据丢失风险。许多消息队列所采用的 “插入 – 获取 – 删除” 范式中,在把一个消息从队列中删除之前,需要你的处理系统明确的指出该消息已经被处理完毕,就是消息的ACK确认机制 ,从而确保你的数据被安全的保存直到你使用完毕。
消息的持久化
对于一些关键的核心业务来说是非常重要的,启用消息持久化后,消息队列宕机重启后,消息可以从持久化存储恢复,消息不丢失,可以继续消费处理。
消息的ACK确认机制
为了保证消息不丢失,消息队列提供了消息Acknowledge机制,即ACK机制,当Consumer确认消息已经被消费处理,发送一个ACK给消息队列,此时消息队列便可以删除这个消息了。如果Consumer宕机/关闭,没有发送ACK,消息队列将认为这个消息没有被处理,会将这个消息重新发送给其他的Consumer重新消费处理。。
4.3、扩展性
因为消息队列解耦了你的处理过程,所以增大消息入队和处理的频率是很容易的,只要另外增加处理过程即可。
4.4、灵活性 & 峰值处理能力
在访问量剧增的情况下,应用仍然需要继续发挥作用,但是这样的突发流量并不常见。如果为以能处理这类峰值访问为标准来投入资源随时待命无疑是巨大的浪费。使用消息队列能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷的请求而完全崩溃。
4.5、可恢复性
系统的一部分组件失效时,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。
4.6、顺序保证
基于Queue消息模型,利用FIFO先进先出的特性,可以保证消息的顺序性。
在大多使用场景下,数据处理的顺序都很重要。大部分消息队列本来就是排序的,并且能保证数据会按照特定的顺序来处理。(Kafka保证一个Partition内的消息的有序性)
4.7、缓冲
有助于控制和优化数据流经过系统的速度,解决生产消息和消费消息的处理速度不一致的情况。
4.8、异步通信
消息的同步和异步收发
同步:
消息的收发支持同步收发的方式。
同时还有另一种同步方式:同步收发场景下,消息生产者和消费者双向应答模式,例如:迪丽热巴写封信送到邮局,然后杨幂从邮局获得了信,然后在写一份回执信,送到邮局,然后迪丽热巴去取,当然迪丽热巴写信的时候就得写明回信地址。
消息的接收如果以同步的方式(Pull)进行接收,如果队列中为空,此时接收将处于同步阻塞状态,会一直等待,直到消息的到达。
异步:
消息的收发同样支持异步方式。
异步发送消息,不需要等待消息队列的接收确认;异步接收消息,以Push的方式触发消息消费者接收消息。
很多时候,用户不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。
4.9、事务支持
消息的收发处理支持事务,如:在任务中心场景中,一次处理可能涉及多个消息的接收、处理,这处于同一个事务范围内,如果一个消息处理失败,事务回滚,消息重新回到队列中。
5、消息队列的应用场景
异步处理:例如短信通知、终端状态推送、App推送、用户注册等
数据同步:业务数据推送同步
重试补偿:记账失败重试
系统解耦:通讯上下行、终端异常监控、分布式事件中心
流量消峰:秒杀场景下的下单状态
发布订阅:HSF的服务状态变化通知、分布式事件中心
高并发缓冲:日志服务、监控上报