MQ 聊聊消息队列那些事


MQ 聊聊消息队列那些事

文章插图
每年的双十一期间,各大电商平台流量暴增 , 同时,电商平台系统的负载压力也会很大 。譬如订单支付的场景,每个订单支付成功后,服务器可能要完成扣减积分、扣减优惠券、扣减商品库存、发短信等一系列操作 。单个用户请求,服务器处理起来并没有什么问题,但是,瞬时并发的多个请求到了服务器,数据库压力上来了,导致请求响应慢,甚至宕机 。
为了解决这个问题 , 我们可能会想到,让数据库处理完一个请求后再处理下一个请求不就好了么 。就这样,消息队列出来了 。消息队列,又称为MQ(Message Queue),它实现了让多个请求以消息的形式排好队,让消息处理程序一个一个的处理 , 有效防止了高并发给服务器带来的压力 。
消息队列应用场景MQ应用的典型场景有异步、削峰、解耦三种 。
异步譬如说一个系统A,它有一个操作处理完自己的逻辑以后需要调用其他系统的接口 , 如下图:
MQ 聊聊消息队列那些事

文章插图
这时候,代码是这样:
public class SystemA { @Resource SystemBapi systemBapi; @Resource SystemCapi systemCapi; @Resource SystemDapi systemDapi; public void doSomething() {//产生一个idlong id = doSomethingAction();//调用其他系统接口systemBapi.doSomething(id);systemCapi.doSomething(id);systemDapi.doSomething(id); }}上面的代码,系统A产生id的逻辑需要50ms,调用系统B的接口需要300ms,调用系统C的接口需要300ms , 调用系统D的接口需要300ms 。一个这样的操作就需要50+300+300+300=950ms 。如果后面还要对接其他系统,这个操作的时间会更长 。
如果调用其他系统接口实时性要求不高,那么,为了提高用户体验和吞吐量,调用其他系统接口的操作就可以交给MQ实现异步操作 。如下图:
MQ 聊聊消息队列那些事

文章插图
系统A执行完了以后,将id给到消息队列中,然后就直接返回了 。
削峰譬如有3台服务器组成集群 , 每台服务器的处理能力是1000个QPS/S,合起来就是3000个QPS/S 。遇上了流量高峰,达到了5000个QPS/S , 请求数量已经超过所有服务器总的处理能力,这时候就可以考虑利用MQ来控制并发数,以免服务器崩溃 。
具体做法是所有请求先进入到MQ,然后每个服务器根据自己的能够处理的请求数去消费消息,也就是无论每秒多个QPS,系统只处理能力范围内的请求数,剩下的请求等有资源再去处理 , 这就是“削峰填谷”,如下图:
MQ 聊聊消息队列那些事

文章插图
解耦解耦就是降低了消息生产者与消费者的耦合度 。耦合度高,程序维护起来就会很麻烦 。譬如,系统A产生了一个id后,需要把id交给系统B、系统C、系统D去处理 。如果由系统A直接去调用其他系统接口 , 系统A的程序代码需要写上调用系统B、系统C、系统D接口的代码 。如果某一天系统C说不需要处理系统A的id了,让系统A不要调用系统C的接口,那系统A要改代码 。又某一天系统E说我要处理系统A的id,让系统A调用系统E的接口 , 系统A又得改代码 。系统A的程序员这样子搞烦不烦?
系统A程序员有一天开窍了,把程序里所有调用外部系统的代码都屏蔽,弄了个MQ中间件,让系统A产生id以后就给到MQ 。然后发个公告告诉所有其他系统的程序员,你们谁想要我这边产生的id你们自己去MQ拿 , 别来烦我 。
MQ 聊聊消息队列那些事

文章插图
这样一来,系统A跟其他系统就解耦了,代码也不用改来改去 。
消息队列要注意的问题问题一:可用性MQ作为整个整个分布式架构的重要部件,如果MQ服务不可用,那整个系统都挂了 。因此,MQ必须要支持集群 。当下主流的MQ中间件都能够不同程度的支持集群 , 实现了MQ服务的高可用 。
问题二:消息丢失消息丢失有可能发生在生产者丢失消息、MQ本身丢失消息、消费者丢失消息3个方面 。