消息队列的应用场景
Posted chen陈序猿
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了消息队列的应用场景相关的知识,希望对你有一定的参考价值。
简单的说,消息队列就是一个传输消息的队列,也叫MQ,职责之一,是消息的通道,职责之二,是存储消息。作为一种跨进程的通信技术,消息队列在互联网应用中发挥着巨大的作用。
数据驱动的任务场景
举个例子,服务B需要服务A的数据来做计算。此时一般有两种解决方案。
一,服务B不断轮询服务A的数据接口拿数据
方式一不够优雅,定时轮询极有可能产生很多的空轮询,同时,定时轮询对实时性要求较高的场景,不太适合。
方式2:mq异步实时推送
方式2更加符合现实场景,我有了,就给你,你不要天天问我,太浪费时间。
再举个例子:互联网公司常常在后半夜跑一些定时任务,用户数据统计,和报表。
最早的玩法,就是,部署N个定时任务。经验认为定时任务1 23:00肯定就能执行完。那么我在23:10 ,让定时任务B开始跑,依赖A的数据。(预留10分钟弹性时间) 23:30定时任务B也应该跑完了,那么我23:40跑定时任务C,依赖B的数据。
这么做的话,一旦中间某个定时任务出了毛病,数据全乱套。预留时间难以预估,如果计算不合理,后果也可以想象。实际中也确实有很多数据B依赖数据A的业务场景吧?如果使用消息队列,怎么做?
应用之间的解耦
互联网业务中,经常有这样的业务场景:比如用户注册。注册成功后,要将用户信息发送给大数据平台。要给分析平台用户数据分析用户行为。要给用户随机生成一两次抽奖资格等。这些时候,用户登录行为不关心大数据那里有没有处理成功,也并不关心数据分析平台有没有拿到数据,用户中心只关心用户注册成功没有。让我们在不使用mq的时候,逐步分析一下直接调用的弊端。
第一版用户登录:
改需求拉:用户注册,要把用户数据发送给大数据平台:
改需求拉,用户注册,用户行为分析平台也要数据。好吧,悲催的用户平台程序员,又要改代码了。
又要改需求拉,随机抽奖平台需要用户登录事件,又得改代码:
长此以往,用户中心程序员天天加班,一个注册事件,关联了相关的若干任务,任何一个调用出错,都将导致用户注册受到影响。由于用户中心对你的服务不信任,内部代码会有很多的try{}catch(){}。代码变的又丑又长,应用之间互相耦合。程序性能逐渐低下。那么如果使用MQ,又怎么玩呢?
上面的例子,是上游应用,根本不关系下游业务的执行情况,可以说是解耦了。但是上游应用依赖下游结果,但是下游太慢了?怎么办?上游调用下游,依赖下游的执行结果,但是下游服务太慢,同步等待在高并发环境下会把服务拖死。(互联网高并发应用,要保证高频接口必须ms级别返回)。那么,此类业务场景,必须也要使用mq。做支付开发的同学一定知道,你在调用第三方支付的时候,支付发起后,支付平台一定会先给你一个同步响应,告诉你,好了,好了,我知道了!同时,最后还要给你一个异步通知。
削峰填谷
实时要求不是很高的业务场景中,经常有服务这样的特征:服务A有请求高峰和请求低峰,服务B没有,服务A高峰的流量,服务B根本扛不住。直接调用,会导致服务雪崩。服务A低峰时,又会导致服务B资源利用率不足。但是,一天的时间整体来看,服务A和服务B能转化的请求数是一致的。此时,MQ的削峰填谷功能就可以使用上了。消费者可以按照自己的成熟能力拉消息消费,而不是推。
分布式事务
mq的第三个应用,就是在分布式事务的应用场景中。大家知道,在传统的单机应用中,利用数据库的特性很容易保证数据的强一致性。(ACID)。但是这种保证数据强一致性的要求,在分布式应用中,很难实现。
虽然业界也提供的事务补偿机制和二阶段提交方案来解决分布式事务问题。但是带来的副作用是巨大的。因为网络是不可靠的。二阶段提交也会造成资源被长期锁住的可能。因此,二阶段提交基本无人使用。那么,使用Mq来实现分布式事务,保证数据最终的一致性,成了常用的解决方案。自己想想,业务之间直接调用,是不是经常出现线上数据不正确的情形。B服务调用C服务,就因为网络闪断那么一下,或者服务C暂时不可用,直接调用失败,数据发生异常。
用mq来实现分布式事务,基本上就是使用的本地事务+消息重试
1,支付平台完成本地事务,将消息持久化。消息推送到消息队列。
2,消息队列收到推送,返回信号给支付平台,信息发送成功。
1和2叫做消息的一条ack。当支付平台收到消息队列的ack回包,才能保证消息投递成功。否则,支付平台要不断发起重试。1和2这个链路任意一个环节都可能出现问题,例如网络闪断。此时,可能造成消息队列收到重复的消息发布。因此,消息队列要对消息进行去重,一般使用全局唯一的msg_id。
3,消息队列将消息push给订单平台,订单平台处理业务逻辑。
4,订单平台业务逻辑处理成功,返回信号给消息队列,消息消费成功。否则,不返回。
3和4叫做一条消息的ack。当订单平台消费消息成功,消息队列收到订单平台的ack回包。才能确定消息是消费成功。3和4这个链路任意一个环节都有可能出现问题:服务刚好宕机,网络闪退,进程异常。此时,可能造成消息队列重新发送消息给订单平台,即使订单平台已经消费成功。订单平台要对消息进行去重,也就是消费者要幂等。(不重复消费。)一般使用消息内容中全局唯一的业务id。
总结
消息队列,在任务调度,解耦应用,尤其在分布式事务场景下,都有非常出色的表现。善用消息队列,能使的软件的质量提高不少。本质上是牺牲强一致性和实时性,换取业务的灵活性。
(完)
chen陈序猿|一起学技术吧
以上是关于消息队列的应用场景的主要内容,如果未能解决你的问题,请参考以下文章