简单介绍一下消息队列MQ

消息队列 MQ(Message Queue),后端通讯的中间件。它屏蔽了复杂的通讯协议,像常用的dubbo、http协议都是同步的,这两种协议很难实现双端通讯,A调用B,B也可以主动调用A,而且不支持长连接。MQ做的就是在这些协议上构建一个简单协议 —— 生产者、消费者模型。

MQ带给我们的不是底层的通讯协议,而是更高层次的通讯模型,它定义了两个对象:发送数据的叫生产者,接受消息的叫消费者,我们可以无视底层的通讯协议,自己定义生产者、消费者。

 觉得业务需要使用mq,就可以使用,没有具体要求什么时候使用

消息队列的三个最主要作用

异步、解耦、削峰

下面通过具体业务场景解释一下这些作用:

这样的设计在业务量不大、并发不大时,可以采用,属于典型的串行化调用,这种设计的好处是代码简单,出现问题很容易定位。

从三高(高并发、高性能、高可用)方面去评价这个设计:

高可用:假如这些服务中有一个宕机或者由于网络波动挂掉,则请求失败,用户频繁看到支付失败的提示,体验感将极差。

高并发:由于这些操作都是一个主线程去执行的,当我们QPS很高时,很容易造成超时。

QPS:系统每秒钟收到的请求

高性能:因为上面这种设计模式是串行的,假设每次网络传输耗时200ms,业务处理需要20ms,完成上面那些操作需要耗时2s,这样用户体验也会很差(想象一下每次下单都需要等2s),如果用户下单后的操作越来越多,耗时只会越来越高。

总结:在大型的互联网项目中,这样传统设计不可取(非核心模块除外)。

并行处理调优

使用线程池改进为并行的设计,再分析一下

高可用:假如这些服务有一个宕机或者由于网络波动而挂掉,理论上讲,如果补偿服务做的出色的话,还是满足高可用的。 (可以用try,catch)

高并发:相比传统的设计,系统的吞吐量可以达到很大程度上的提升。

高性能:相比传统的设计,因为很多业务是并行执行的,所以相当于只有200*2+20,就可以返回。

上面这个设计看起来还是不错的设计,所以在很多这种串行调用、多次io的时候我们就可以采用这种方案,上面这种设计也是多线程的一种实战应用。

但还是存在一些弊端,分析一下:

  1. 系统的可扩展性太差了。上面只是列举了4步,但是实际上会有几十步,这几十步放到代码里就会像屎堆一样,可维护性极差。每次加一个步骤,都要多调一个接口,然后重新发布一下服务。

  2. 系统的耦合性太高了。如果几十个http调用放到一起并发执行,很有可能会影响其他的点,尤其是淘宝京东这种秒杀敏感的业务,和钱挂钩的业务,很容易出现p0级别的bug。

  3. 使用的业务本身的线程池,在并发很多的情况下,容易造成cpu的竞争。

于是,进一步演化。

多线程处理三种方案

  1. 主线程交给线程池里的线程去执行时,主线程等待,等所有任务执行完之后,主线程再去接着执行(查询做聚合的时候)。

  2. 主线程交给线程池去处理,就不管了(删除或修改一个东西,需要耗时2s)

  3. 主线程交给线程池去处理,主线程继续去执行其他的任务,等线程池里的任务执行完之后,去通知主线程,主线程在接着去执行后续的逻辑。

使用消息队列

还是从三高的层面去分析:

高可用:当系统里的一个服务模块宕机了,不会影响到其他服务。 (可以通过数据补偿或者分布式事务来保证数据最终一致性)

高性能:用户下单,将下单所需要的数据都放到消息队列里,就直接返回了,所有耗时相当于是网络传输所需耗时。

高并发:由于消息队列不处理任何业务上的逻辑,所以它支持的并发是百万级别的。假如有100万个用户下单,100万的数据放到消息队列里,连接消息队列的服务慢慢消费即可,也不至于造成瞬间有百万请求进来,将服务压垮。

三大优点

解耦:就像高可用里面说的一样,发淘金币服务挂了,与下单服务没什么关系,还是可以正常下单,只不过后期可以数据补偿或者分布式事务解决这个问题。

削峰:比如说平时的服务就只能支撑几万的QPS,像淘宝京东那种秒杀,如果采用第二种方案,服务突然打进来那就会直接被压死了。但是如果采用消息队列,秒杀进来的所有请求都不会直接打到具体服务上,而是先打到消息队列里,然后后面的服务再慢慢消费。

可以参考淘宝京东双11秒杀的时候,慢是慢了点,起码服务没挂。秒杀结束之后,服务还能正常运转。

消息队列就像是一个三峡大坝,用来拦截上游给的压力。

异步:连接消息队列的服务可以异步去执行,且每次多增加一个步骤,下单的代码是不需要改动的,只需要再增加一个消费者即可。

也是有缺点的!

1. 增加了系统复杂性

如果业务量不大,并发也不高,就没必要使用消息队列。

2. 事务问题

事务问题其实是分布式系统肯定会存在的一个问题,只不过消息队列更严重一些。一般解决方案有两种,第一种就是采用分布式事务,这个下单的里涉及的所有服务放到一个事务里面,要么都成功,要么都失败。第二种就是,消费者做好合理的数据补偿措施,比如说,消息重试,人工刷数据等等。

3. 可用性

刚才说的解耦,其实是系统的各个模块之间的解耦,但是这些模块都和消息队列关联,如果消息队列挂了,就真的下不了单了。为了保证可用性,我们可以采用消息队列集群,前端流量限流等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值