赞
踩
开发中消息队列通常有如下应用场景:
1、任务异步处理。
将不需要同步处理的并且耗时长的操作由消息队列通知消息接收方进行异步处理。提高了应用程序的响应时间。
2、应用程序解耦合
MQ 相当于一个中介,生产方通过 MQ 与消费方交互,它将应用程序进行解耦合。
消息队列
使用队列来通信的组件,把要传输的消息放在队列中。
RabbitMQ
它是实现了高级消息队列协议(AMQP)的消息中间件。
1 - 系统解耦:解耦消息生产者和消费者之间的关系
2 - 异步调用:用户调用接口时,由于接口之间调用导致用时时间比较久,用户体验不好。
调用接口后将消息放入到MQ后就返回,用户体验好,最终一致性由MQ来保证
3 - 流量削峰:减少高峰时期对服务器压力,先把请求放到MQ中,系统根据实际能处理的并发量来消费请求
1 - 系统可用性降低。如果MQ挂了,整个系统就不能服务了
2 - 系统复杂性提高。消息丢失、消息重复消费、消息重复发送、消息顺序错乱等问题
3 - 一致性问题。将消息放到MQ后就返回给用户成功的信息,但是其他系统消费消息时,
若某个系统失败了,导致数据不一致
消息过期时间
目前有两种方式设置消息的过期时间,一是通过队列属性设置,二是通过消息单独设置。
如果两种方式同时使用,以最小值为准。
队列过期时间
通过 channel queueDeclare 方法中的 expires 参数可以控制队列被自动删除前处于未使用状态的时间
。未使用的意思是队列上没有任何的消费者,队列也没有被重新声明,并且在过期时间段内也未调用过Basic Get命令
DLX ,全称为 Dead-Letter-Exchange ,可以称之为死信交换器。
当消息在一个队列中变成死信 (dead message) 之后,它能被重新被发送到另一个交换器中,
这个交换器就是 DLX ,绑定 DLX 的队列就称之为死信队列。
消息变成死信一般由于以下几种情况:
延时队列
在rabbitmq中可通过过期时间(TTL)和死信队列(DLX)实现延时队列
优先级队列
可设置队列支持的最大优先级,然后发送消息时设置消息的优先级。
但是要注意这种情况只在消费者能力小于生产者,有消息堆积时有效。
RabbitMQ的持久化分为3个部分:交换器的持久化、队列的持久化和消息的持久化。
但是如果将所有消息持久化,将会严重影响rabbitmq的性能。
即使将交换器、队列和消息都设置了持久化,也不能保证消息100%不丢失。
资料上说rabbitmq可以保证消息的有序,其实是不严谨的。
在不使用任何 RabbitM 高级特性 ,也没有消息丢失、网络故障之类异常的情况发生,并且只有一个消费者的情况下
如果有多个生产者同时发送消息,无法确定消息到达 Broker 的前后顺序,也就无法验证消息的顺序性。
需要业务方使用 RabbitMQ 之后做进一步的处理,比如在消息体内添加全局有序标识(类似SequenceID) 来实现。
RabbitMQ 3.6.0 版本开始引入了惰性队列 lazy Queue 的概念。
惰性队列会尽可能地将消息存入磁盘中,而在消费者消费到相应的消息时才会被加载到内存中,
它的一个重要的设计目标是能够支持更长的队列即支持更多的消息存储
。当消费者由于各种各样的原因(比如消费者下线、宕机或者由于维护而关闭等〉
致使长时间内不能消费消息而造成堆积时惰性队列就很有必要了。
channel.basicConsume
将 channel(信道)设置为推模式,消息可用时自动将消息推送给消费者channel.basicGet
拉消息消息发送给消费者后,默认是自动确认,如果消费者未能消费成功,则消息丢失。
通过显式确认可以保证只有当消息处理完成并收到Ack后才从队列中删除。
但是存在的问题是:
1)消息太多全部传给消费者,可能造成消费者内存爆满;
2)消息处理慢时,想让别的消费者一起处理,但是这些消息都被原来的消费者接收了,这些消息不会再发送给新添加的消费者
Qos可以解决上述问题,需要开启消息的显式确认,设置每次传输给消费者的消息条数为n,
消费者处理完n条消息后再获取n条消息进行处理;而新增消费者时,消息可以立即发送给新的消费者。
默认轮训策略
公平分发(QoS):给空闲的消费者发送更多的消息(当消费者有x条消息没有响应时,不再给该消费者发消息)
生产者
confirm机制:
重复投递的原因:等待超时后,需要重试。
避免重复投递:消息生产时,生产者发送的消息携带一个Message ID
(全局唯一ID),
作为去重和幂等的依据,避免重复的消息进入队列
重复消费的原因:消费者接收消息后,在确认之前断开了连接或者取消订阅,
消息会被重新分发给下一个订阅的消费者。
避免重复消费:消息消费时,要求消息体中必须要有一个全局唯一ID,
作为去重和幂等的依据,避免同一条消息被重复消费
alpha
:消息内容(包括消息体、属性和headers) 和消息索引都存储在内存中beta
:消息内容保存在磁盘中,消息索引保存在内存中gamma
:消息内容保存在磁盘中,消息索引在磁盘和内存中都有delta
:消息内容和索引都在磁盘中存储延迟消息,消息被发送后不想让消费者立即拿到消息,要等待特定时间后才能拿到消息。
实现方式
3.6.x之前,死信队列+TTL过期时间可以实现延迟队列。
3.6.x开始,延迟队列插件
应用场景
x天自动确认收货、自动默认评价。
12306购票支付确认页面,如果30分钟没有付款将自动取消订单。
每台机器上启动一个RabbitMQ实例,而创建的queue只放在一个实例上,其他实例同步queue的元数据。
消费时如果连接到了另一个实例上,则实例会从queue所在的实例上拉取数据
多个实例服务一个queue
RabbitMQ的元数据和queue里的消息都会存在于多个实例上,
每次消息进入队列,会自动把消息同步到多个实例的队列中
分为一个master和多个slave。所有的操作最终都会到master上操作
保证消息可靠性:
RabbitMQ的优缺点:
优点
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。