MQ 消息队列

经验 77 浏览

什么是队列?

队列(Queue)是先进先出的线性数据结构。和堆栈一样的,队列只允许在后端进行插入操作:进队;在前端进行删除操作:出队具体应用中通常用链表和数组来实现。

什么是消息队列?

消息队列,简称MQ(Message Queue)。我们可以简单理解为:把要传输的数据放在队列中。

把数据放到消息队列叫做生产发送消息的系统称为生产者

从消息队列取出数据叫做消费接受消息的系统称为消费者

有哪些消息模式?

JMS规范目前支持两种消息模式:点对点(Point To Point, queue)和发布-订阅(Publish-Subscribe,topic)。

点对点模式消息生产者生产消息发送到queue中,然后消息消费者从queue中取出并且消费消息。消息被消费以后,queue中不再有存储,所以消息消费者不可能消费到已经被消费的消息。queue支持存在多个消费者,但是对一个消息而言,只会有一个消费者可以消费。

发布-订阅模式消息生产者(发布)将消息发布到topic中,同时有多个消息消费者(订阅)消费该消息。和点对点方式不同,发布到topic的消息会被所有订阅者消费。

这两种模式主要区别或解决的问题就是发送到队列的消息能否重复消费(多订阅)。

为什么使用消息队列?

通常随着业务体量的增加以及业务场景复杂度的提高,微服务的设计思想和分布式的部署方式的使用。很多场景单机的技术栈和中间件已经不够用了;对系统的友好性也下降了;系统间耦合性也提升了;代码复杂度增加了,出现错误也很难排查等。

异步处理提高系统性能

在复杂业务流程中,用户的许多非核心流程也需要对数据库进行写操作,由于数据库对写操作是阻塞的,并发时数据库压力剧增,响应速度就会变慢(如果是业务分离的话,还要加上接口耗时)。但是在使用消息队列之后,用户的核心流程处理完,非核心流程将数据发送给消息队列之后就结束对消息的处理,再由消息队列的消费者进程从消息队列中获取数据,异步写入数据库,因此响应速度得到大幅改善。

降低系统间的耦合性

分布式消息队列使用发布-订阅模式工作,生产者和消费者之间没有直接耦合,生产者将消息发送至消息队列即结束对消息的处理(不关心谁订阅),消费者从分布式消息队列获取该消息后进行后续处理。对新增业务,只要对该类消息感兴趣,即可订阅该消息,对原有系统和业务没有任何影响,实现了解耦,从而实现业务的可扩展性设计。

应用场景?

实际应用中有很多地方会用到消息队列,我们简单列举几个有代表性的:

| 异步处理

例如:订单系统的下单流程,简单业务可能支付成功后就结束,但是100个产品有100个idea。

考虑流程:

step1,用户开始下单

step2支付成功

step3,发短信

step4红包系统

step5优惠券系统

step6积分系统

...

链路只会越来越长,几十个都不奇怪!这时候系统基本都是分布式部署的,通常都是请求接口。接口优化的再好平均响应时间也得50ms吧?十个以上流程轻松10秒就过去了,而且网络是有波动的,高并发的时候来一下,心都是跟着颤抖。即使不是分布式部署,同步处理每个流程都要依次对数据库进行写操作,阻塞下来时间也很长。

为了用户体验,我们不可能让用户等这么长时间。支付成功之后其它的流程异步处理,并且告知用户支付成功。不阻塞主流程,提高了系统响应时间,提升了用户体验。

| 应用解耦

在Java等语言中,可能会开启多个线程去同时执行达到相同的目的,但是对于PHP这种单线程来说就没这种待遇了啊,还要开启swoole协程。而且高并发情况下可能出现异常,影响系统稳定性。

最主要的是,我是负责订单系统的,你每来个idea都需要我去改代码,接口加密或者验签方式改变我也要跟着改,假如没有通知到我或者我没看见邮件,系统出错这个锅还要我自己背,这个耦合性也太强了。

使用消息队列,我只要将订单支付消息发布到topic,后面的业务对我来说就是无感知的。发短信业务需要知道订单支付状态,那就订阅这个topic;积分系统要加减积分,那也订阅这个topic。根据队列中的数据,处理自己的业务,每个系统只要维护好和自己相关业务就行,极大的降低了系统间的耦合性。

| 削峰/限流

并发时大量请求过来,但是我们的服务器处理速度跟不上,根据实际服务器处理能力,将请求进入消息队列,队列满的则让用户继续等待,达到限流的目的。

|  版权声明:本文为博主原创文章,转载请注明出处。