MQ是什么?
MQ全称Message Queue,中文名称消息队列。顾名思义,它就是一个队列,简单来说就是一个应用程序A将数据丢到一个队列中,由另一个应用程序B从队列中拿到这个数据,再去做一些其他的业务操作。我们把应用程序A叫做生产者,应用程序B叫做消费者,它们之间传输的数据称作消息。
MQ的使用场景
解耦
假设系统A通过调用接口推送数据给B、C、D,如果后续系统E也需要被推送、或者B不再需要被推送呢?那我们就需要修改系统A的代码,加上给E推送数据的逻辑,去掉给B推送数据的逻辑。显然A系统和其他系统严重耦合,在这个场景中,如果使用 MQ,通过发布订阅模型,就可以实现A和其他系统的解耦。A 产生一条数据,发送到 MQ ,哪个系统需要就去订阅消费,如果某个系统不再需要,取消对消息的订阅即可。
异步
将一些无需即时返回且耗时的操作提取出来,进行了异步处理,而这种异步处理的方式大大的节省了服务器的请求响应时间,从而提高了系统的吞吐量。
实例:之前有一个项目,用户在后台上传PPT,系统先将PPT保存到文件服务器,拿到PPT的地址再调用拆图服务,将PPT拆分成一张张的图片,拆分后将图片地址保存到数据库,因为拆图操作比较耗时,整个过程大约得要十几秒。
那像这种耗时的操作,如果操作员在上传PPT的时候,先不说接口超不超时的问题,就光页面卡在哪里十几秒,谁能受得了?所以当时就用到了消息队列,上传PPT成功,就给用户返回成功,将PPT的服务器地址丢到队列中,消费者拿到地址再去做拆图操作,如果消费失败再补偿重试,重试3次仍失败,则触发邮件报警。
这个场景对于生产者而言,你不用知道具体的消费者是谁、在哪。你要做的只是将消息向你们约定好的地址进行发送,你的任务就完成了。对应的服务自然能监听到你发送的消息,进行后续的操作。这就是消息队列最大的特点,将同步操作转为异步处理。
削峰限流
商城秒杀活动我们都不陌生,对于商城系统,可能在0点左右会有个短暂的高峰期,但其余时间的并发量也没那么高,假如我们的后台系统直接操作数据库,平时可能没什么问题,但如果突然有很高的的并发量进来,就会因为MySQL并发量过大导致系统瘫痪。
如果使用MQ,请求会短期积压在MQ中,后台系统从MQ中分批拉取消息,从而保证数据库不会被压垮。等高峰期一过,系统就会将MQ中积压的消息慢慢解决掉。这就是MQ的"削峰限流"作用。
MQ对系统的影响
1、系统的可用性降低
系统的可用性是指系统服务不中断运行的时间占实际运行时间的比例。高可用就是指系统服务不中断运行时间占实际运行时间的比例大。
系统引入的外部依赖越多,越容易挂掉,所以引入MQ后系统的可用性可能会降低。
2、系统的复杂度增加
引入MQ以后要多考虑很多方面的问题,比如怎么保证消息的可靠传输、怎么保证消息的幂等性等,提高了系统的复杂度。
什么是RabbitMQ的幂等性
1. 什么是幂等性?
幂等性的实质是:对于一个资源,不管你请求一次还是请求多次,对该资源本身造成的影响应该是相同的,不能因为重复相同的请求而对该资源重复造成影响。注意关注的是请求操作对资源本身造成的影响,而不是请求资源返回的结果。
如select * from t_user where id>10这条语句,假如在一次查询后数据库进行了insert或update操作,那么第二次再查时返回的结果可能与第一次不同,但这个操作是符合幂等性的,因为我们说过关注的是对资源的影响,不是返回的结果,虽然两次查询的返回结果不同,但select不管执行多少次,对数据库中的数据资源本身都不会产生任何影响。
幂等性包括:
① 一次或多次请求,对资源均不会造成影响,比如select操作;
② 第一次请求对资源产生了影响,后面再发出多个相同的请求,与发出单个请求具有相同的效果,不能重复对资源产生影响。比如支付宝转账,手抖重复提交了2次,第一次扣款成功,余额减少100元,第二次就不能再重复扣款了。
③ 需要说明的是网络超时、服务宕机等问题,不是幂等的范围。
这里说明下:声明为幂等的服务会认为调用方调用失败是常态,并且允许在调用失败后重试。
2. RabbitMQ中的幂等性
1. 首先看下导致非幂等的情况有哪些?
① consumer接收到消息处理完成后,在给Broker返回ack途中网络中断,Broker未收到确认信息,根据RabbitMQ的重试补偿机制,则会把这条消息再重发给其他的消费者或等网络重连后再发送给该消费者,造成了消息的重复消费。
② 或者在开启生产者confirm模式下,生产者已经把消息发送到Broker,但在Broker回传ack确认时网络中断,生产者也会重新发送刚才的消息,造成Broker收到了重复的消息,最终将两条重复的消息发送到消费端,造成了消息的重复消费。
通过以上两种场景我们看出,其实MQ的幂等性保障应该在消费端,要保证MQ的幂等性,就要保证消费者不会重复消费相同的消息。
RabbitMQ常用的队列模式
RabbitMQ常用的队列模型有五种,分别是:简单队列、工作队列、发布订阅 ( 多对多 )、路由模式 ( 一对一 )、主题模式 ( 一对多 )。
简单队列模式
一个生产者,一个消费者;就是简单的队列方式。
工作队列模式
一个生产者,多个消费者;并且一条消息只能被一个消费者消费,不能被多个消费者重复消费。
发布订阅模式
发布订阅模式涉及到RabbitMQ的交换机概念,RabbitMQ的交换机有三种类型,发布订阅模式的交换机类型是 fanout ;
生产者产生的消息并不是直接发送给消息队列Queue的,而是要经过Exchange(交换器),由Exchange再将消息广播到下方所有Queue
路由模式
发布订阅模式涉及到RabbitMQ的交换机概念,RabbitMQ的交换机有三种类型,发布订阅模式的交换机类型是 direct ;
生产者产生的消息指定Exchange(交换器)并携带 Binding ( key ),Exchange再通过Binding查找下方Queue队列并推送消息。
主题模式
发布订阅模式涉及到RabbitMQ的交换机概念,RabbitMQ的交换机有三种类型,发布订阅模式的交换机类型是 topic;
主题模式与路由模式相似,区别在于交换机通过Binding (key)查找的方式替换成通过Routing (key)规则匹配;
由Queue队列设置过滤规则,选择性接收消息,规则( * : 替代一个单词;# : 替代 0 或多个单词 ),如下图所示
作者:怒吼的萝卜