在越来越多的系统中我们经常会看到mq的身影,mq为高并发系统解决了并发引起的问题,解决了限流,分布式事务等等问题。

消息队列并发 消息队列高并发的原理_算法

为啥会采用mq来解决高并发问题

比如经常我们的系统会遇到这样类似的问题:用户下单完成之后,我们就需要给用户发送短信,通知用户下单成功。如果按照常规的方法,我们就会在代码中下单完成之后,同步调用发短信的业务。但是,如果发送短信的代码异常了,那下单的这个业务逻辑就走不下去了,严重影响下单的操作。这样就导致全天没有订单。况且,这个发送短信是不重要的业务,下订单才是系统关心的问题。如果短信发送不成功,我们可以重试或者其他服务去独立调用的话,就可以帮助我们解耦,独立运行发送短信,下单业务正常执行。同时,在高并发的情况下,大量请求打到下单数据库中,这样导致数据库奔溃,系统瓦解。所以,我们还要考虑限流和数据库保护问题。

这个时候,消息队列就派上用场了

消息队列的好处

消息队列就可以单独的执行独立的业务,比如发送短信的业务,但是它不会影响到主业务,无论发送短信失败与否,主业务正常执行。下单完成之后,通知发送短信服务即可,就可以干别的事了。这样就实现了最终一致性的问题。

消息队列特性

  • 业务无关,做消息分发
  • 先进先出
  • 节点动态删除,可持久化到硬盘
  • 高吞吐量,通信效率高

消息队列并发 消息队列高并发的原理_rabbitmq_02

高并发中使用消息队列的主要原因

业务解耦

上面提到的下单的业务逻辑,用户不需要等发送短信成功之后,才算下单成功。mq只负责接收到消息,完成一个独立的功能,不影响到主业务逻辑。用户下单之后,提示用户下单成功,用户不需要等任何结果。等发送短信成功之后,用户就知道下单的结果了。这样的话,业务就解耦了,下单和发送短信就分配给不同的人员进行开发,相互不影响了。

最终一致性

什么是最终一致性?就是二个系统的状态最终保持一致,要么成功,要么失败,只是时间不同而已。mq实现最终一致性的解决方案就是:把要处理的任务保存队列中,然后保证这个任务一定会被执行。如果执行失败了,在利用这个队列的消息,不断重复执行,知道成功。成功之后,二个系统的状态就一直了。

比如说a转账到b,a减少100,最终b肯定增加了100.无论中间经历了什么异常,但是最终是这样的结果,这就是最终一致性的简单解释了。

消息的幂等性

消息再发送的时候,可能会发送多条一样的数据,这个时候队列中就会有多条消息,解决幂等性的问题,就是我们的业务代码中,根据自己的逻辑进行去重了。

rpc和消息队列

消息队列不是万能的,如果对于强一致性的问题,或者是对延迟敏感的,就采用rpc来实现比较靠谱了。

对于一些无关痛痒,或者对于别人非常重要但是对于自己不是那么关心的事情,可以利用消息队列去做。

支持最终一致性的消息队列,能够用来处理延迟不那么敏感的“分布式事务”场景,而且相对于笨重的分布式事务,可能是更优的处理方式。

当上下游系统处理能力存在差距的时候,利用消息队列做一个通用的“漏斗”。在下游有能力处理的时候,再进行分发。

如果下游有很多系统关心你的系统发出的通知的时候,果断地使用消息队列吧