说说MQ

2016-10-24

MQ简介

MQ是什么

MQ(message queue)消息队列,作为一种通信方式,起到接收消息和消息投递的媒介作用。举个例子,邮递员会收集到寄信人的信件,然后按信件地址进行投递,收件人收到信件。这里邮递员就作为寄信人和收信人通信的中间人。软件系统中的MQ,一般作为进程间或者系统间通信的一种方式,能够降低消息发送者和接受者的耦合,提高协作效率。

MQ能解决什么问题

依赖解耦

MQ的一个重要作用就是降低依赖,使用消息发送者与接受者直接的耦合度降到最低。

在之前一个支付项目中,我们使用到第三方支付,这边先介绍下第三方支付的钱是怎么支付使用的。用户在平台支付钱给供应商时,钱会先进入主商户(平台在第三方支付开通的账号),然后在把钱转给供应商的子商户(供应商在主商户下的子商户),这里就涉及到先充值后转账的两个流程来完成一个支付功能。在发起支付请求并支付成功后,第三方支付会进行支付成功的回调,在回调时进行转账以及业务后续流程。流程上是没有问题的,但是第三方支付成功后,钱并没有马上进入到主商户会有一定延时(第三方支付有入账的概念),导致回调中执行的转账会失败,因为钱还没到账余额不足以支付。

这个例子主要问题是,如何保证支付回调后,即能够转账成功,同时不影响后续业务流程

  • 方案一:用户在支付成功后,发现报错业务流程走不下去了,此时用户支付的钱在平台的余额里面,用户可以在此去使用余额支付,此时如果在第三方的主商户的钱到账的话,可以成功,否则还是失败。重复几次后,肯定会成功的。但是这样体验太差。

  • 方案二:把回调中的转账和业务流程隔离开,使转账的结果不影响业务的执行,用户关心的是支付成功后业务继续执行,而不关心钱什么时候转账成功,只要我们保证钱一定会转成功就行,而且这边的延时一般也在1-5分钟内,所以还是可以接受的。

在决定了使用方案二后,我们引入了MQ(nsq)来解决这个问题。在回调中不在直接进行转账功能,而是把转账变成消息发送到nsq。并由nsq的客户端去订阅转账的消息,在客户端收到转账消息后,进行转账功能。这样既保证了业务的流程,又解决了转账因延迟导致的失败问题。

最终一致性

最终一致性可以理解为多个业务结果状态最终达到预期状态或者多个系统之间最终达到某个预期状态,如上述例子中,一个支付里面包含两个动作(充值与转账),这边最终一致性就是要保证支付的最终结果是充值成功,转账也成功,否则都不成功。MQ可以用来保证支付的最终一致性的问题。在上面的例子中nsq可以保障消息至少被消费一次,如果在消费转账消息的时候,转账失败,客户端只要告诉nsq这个消息消费失败,那么这个消息就会重新入列,供再次消费,直到转账成功,消息被成功消费。

广播

MQ另一个重要作用是进行消息的广播,由客户端去决定是否消费改消息。如多个系统需要要从数据中心系统同步数据,当数据中心数据更新时,可以广播数据更新的消息,由下游来决定是否消费,这样在新系统需要同步数据中心数据时,可以很好的接入,极大的减少了对接的开发量,提高了系统的可扩展性。

在APP端的信息推送,我觉得也是可以通过MQ来做消息分发和广播。由APP的服务器(可能多台)去订阅MQ的消息服务。

错峰与流控

由于系统服务上下游间提高服务的能力大不相同,如果下游服务的能力太差就会把上游的服务能力也降低,导致体验太差。比如短信服务,短信服务一般使用的是第三方的服务,服务能力是不受控制的。所以我们可以通过MQ来把发短信的功能通过消息的方式来实现,通过MQ来缓冲短信系统的压力,我们可以有多个短信服务对应多个MQ客户端订阅者。也可以通过统计各客户端消费消息的情况来实现流量控制和负载。这样能有效提供自身系统的性能,同时降低系统与外部系统服务之间的耦合度。

MQ要具备什么功能

writing…

可以选择的MQ

  • RabbitMQ

  • Kafka

  • NSQ

vs

总结

上面简单介绍了MQ的使用场景,总体来说MQ可以降低系统间的耦合度,可以分离非强关联业务流程,提高系统的可扩展性。但是MQ也不是万能的,还是要结合实际业务,来具体判断是否可以引入MQ。在MQ的选择上,选择团队熟悉的技术,尽量是轻量级的,使团队能够快速上手,后续运维也方便。

参考资料