究竟什么时候该使用MQ?

原创: 58沈剑 架构师之路  昨天

任何脱离业务的组件引入都是耍流氓。引入一个组件,最先该解答的问题是,此组件解决什么问题。

MQ,互联网技术体系中一个常见组件,究竟什么时候不使用MQ,究竟什么时候使用MQ,MQ究竟适合什么场景,是今天要分享的内容。

MQ是什么?消息总线(Message Queue),后文称MQ,是一种跨进程的通信机制,用于上下游传递消息。画外音:这两个进程,一般不在同一台服务器上。 

在互联网架构中,MQ经常用做“上下游解耦”:(1)消息发送方只依赖MQ,不关注消费方是谁;(2)消息消费方也只依赖MQ,不关注发送方是谁;

画外音:发送方与消费方,逻辑上和物理上都不依赖彼此。

什么时候不使用MQ?当调用方需要关心消息执行结果时,通常不使用MQ,而使用RPC调用

ret = PassportService::userAuth(name, pass);

switch(ret){

    case(YES) : return YesHTML();

    case(NO) : return NoHTML();

    case(JUMP) : return 304HTML():

    default : return 500HTML();

}

如上例所示,上游调用Passport服务,处理结果不同,业务会走不同的逻辑处理分支(登录成功,登录失败,执行错误等),即“处理结果强依赖”,此时应该使用RPC调用。画外音:绝大部分情况,应该使用RPC。 此时如果强行使用MQ呢

如果强行使用MQ通讯,调用方不能直接告之用户登录成功又或失败,则要等待另一个MQ通知回调。这么玩,不但使得编码复杂,还会引入消息丢失的风险,中间多加入一层,多此一举。 究竟什么时候使用MQ呢?下面四类典型场景,应该使用MQ。
典型场景一:数据驱动的任务依赖
什么是任务依赖?举个栗子,互联网公司经常在凌晨进行一些数据统计任务,这些任务之间有一定的依赖关系,例如:(1)task3需要使用task2的输出作为输入;(2)task2需要使用task1的输出作为输入;这样的话,tast1, task2, task3之间就有任务依赖关系,必须task1先执行,再task2执行,载task3执行。
对于这类需求,通常怎么实现呢?常见的玩法是,crontab人工排执行时间表。

如上图,手动设定如下:(1)task1,0:00执行,经验执行时间为50分钟;(2)task2,1:00执行(为task1预留10分钟buffer),经验执行时间也是50分钟;(3)task3,2:00执行(为task2预留10分钟buffer); crontab手动排表有什么坏处呢?(1)如果有一个任务执行时间超过了预留buffer的时间,将会得到错误的结果,因为后置任务不清楚前置任务是否执行成功,此时要手动重跑任务,还有可能要调整排班表;(2)总任务的执行时间很长,总是要预留很多buffer,如果前置任务提前完成,后置任务不会提前开始;(3)如果一个任务被多个任务依赖,这个任务将会称为关键路径,排班表很难体现依赖关系,容易出错;(4)如果有一个任务的执行时间要调整,将会有多个任务的执行时间要调整;

无论如何,采用“crontab排班表”的方法,各任务严重耦合,谁用过谁痛谁知道。画外音:用过的,痛过的,请留言。 
应该如何优化呢?采用MQ解耦。

如上图,任务之间通过MQ来传递“开始”与“结束”的通知:(1)task1准时开始,结束后发一个“task1 done”的消息;(2)task2订阅“task1 done”的消息,收到消息后第一时间启动执行,结束后发一个“task2 done”的消息;(3)task3同理; 采用MQ有什么好处呢?(1)不需要预留buffer,上游任务执行完,下游任务总会在第一时间被执行;(2)依赖多个任务,被多个任务依赖都很好处理,只需要订阅相关消息即可;(3)有任务执行时间变化,下游任务都不需要调整执行时间; 需要特别说明的是,MQ只用来传递上游任务执行完成的消息,并不用于传递真正的输入输出数据。 典型场景二:上游不关心执行结果
上游需要关注执行结果时要用“RPC调用”,上游不关注执行结果时,使用MQ。 举个栗子,58同城的很多下游需要关注“用户发布帖子”这个事件,比如:(1)招聘用户发布帖子后,招聘业务要奖励58豆;(2)房产用户发布帖子后,房产业务要送2个置顶;(3)二手用户发布帖子后,二手业务要修改用户统计数据; 
对于这类需求,可以采用什么方式实现呢?

比较无脑的,可以使用RPC调用来实现:帖子发布服务执行完成之后,调用下游招聘业务、房产业务、二手业务,来完成消息的通知。
但事实上,这个通知是否正常正确的执行,帖子发布服务根本不关注。 通过RPC来传递不需要知道处理结果的通知,有什么坏处呢?(1)帖子发布流程的执行时间增加了;(2)下游服务当机,可能导致帖子发布服务受影响,上下游逻辑+物理依赖严重;(3)每当增加一个需要知道“帖子发布成功”信息的下游,修改代码的是帖子发布服务;画外音:这一点是最恶心的,属于架构设计中典型的反向依赖。
如何来进行优化呢?采用MQ解耦,代替RPC。

如上图所示:(1)帖子发布成功后,向MQ发一个消息;(2)哪个下游关注“帖子发布成功”的消息,主动去MQ订阅; 如此一来,有什么好处呢?(1)上游执行时间短;(2)上下游逻辑+物理解耦,除了与MQ有物理连接,模块之间都不相互依赖;(3)新增一个下游消息关注方,上游不需要修改任何代码; 典型场景三:上游关注执行结果,但执行时间很长
有时候上游需要关注执行结果,但执行结果时间很长(典型的是调用离线处理,或者跨公网调用),也经常使用回调网关+MQ来解耦。 举个栗子,微信支付,跨公网调用微信的接口,执行时间会比较长,但调用方又非常关注执行结果,此时一般怎么玩呢?

一般采用“回调网关+MQ”方案来解耦:(1)调用方直接跨公网调用微信接口;(2)微信返回调用成功,此时并不代表返回成功;(3)微信执行完成后,回调统一网关;(4)网关将返回结果通知MQ;(5)请求方收到结果通知; 这里需要注意的是,不应该由回调网关来RPC通知上游来通知结果,如果是这样的话,每次新增调用方,回调网关都需要修改代码,仍然会反向依赖,使用回调网关+MQ的方案,新增任何对微信支付的调用,都不需要修改代码。 结尾总结MQ是一个互联网架构中常见的解耦利器。

什么时候不使用MQ?上游实时关注执行结果,通常采用RPC。 什么时候使用MQ?(1)数据驱动的任务依赖;(2)上游不关心多下游执行结果;(3)异步返回执行时间长;

究竟什么时候该使用MQ?的更多相关文章

  1. 为什么会需要消息队列(MQ)?

    为什么会需要消息队列(MQ)? #################################################################################### ...

  2. 消息队列一:为什么需要消息队列(MQ)?

    为什么会需要消息队列(MQ)? #################################################################################### ...

  3. 浅谈服务间通信【MQ在分布式系统中的使用场景】

    解决的问题 一项技术的产生必然是为了解决问题而生,了解了一项技术解决的问题,就能够很轻松的理解这项技术的设计根本,从而更好地理解与使用这项技术. 消息中间件和RPC从根本上来说都是为了解决分布式系统的 ...

  4. 到底什么时候该使用MQ?

    一.缘起 一切脱离业务的架构设计与新技术引入都是耍流氓. 引入一个技术之前,首先应该解答的问题是,这个技术解决什么问题. 就像微服务分层架构之前,应该首先回答,为什么要引入微服务,微服务究竟解决什么问 ...

  5. 朱晔的互联网架构实践心得S2E1:业务代码究竟难不难写?

    注意,这是我的架构实践心得的第二季的系列文章,第一季有10篇你也可以回顾. 见https://www.cnblogs.com/lovecindywang/category/1296779.html 最 ...

  6. 架构-到底什么时候该使用MQ【转】

    点击:<查看原文> 一.缘起 一切脱离业务的架构设计与新技术引入都是耍流氓. 引入一个技术之前,首先应该解答的问题是,这个技术解决什么问题. 就像微服务分层架构之前,应该首先回答,为什么要 ...

  7. 使用MQ要考虑的问题

    一般现代软件系统都会用到MQ,几乎所有开发人员也都会想到用MQ,但真正能用好的人估计不多,因为要用好MQ有很多方面问题要考虑: 1.在原直接交互的系统间增加MQ中间层,MQ的性能.可靠程度会严重影响原 ...

  8. 【转】到底什么时候应该用MQ

    原文地址:http://zhuanlan.51cto.com/art/201704/536407.htm 一.缘起 一切脱离业务的架构设计与新技术引入都是耍流氓. 引入一个技术之前,首先应该解答的问题 ...

  9. mq使用场景、不丢不重、时序性

    mq使用场景.不丢不重.时序性.削峰 参考: http://zhuanlan.51cto.com/art/201704/536407.htm http://zhuanlan.51cto.com/art ...

随机推荐

  1. AcWing 走廊泼水节 题解

    这道题大致题意就是让一棵树任意两点有连边(也就是完全图),但是补完后最小生成树是一开始的那棵树,问最小加的边权之和是多少. 了解题意后,我们可以想到用Kruskal(废话),当每两个集合合并的时候,除 ...

  2. idea2020.1.2破解,亲测可行,激活至2089年!

    一.下载最新版IDEA2020安装包 官网:https://www.jetbrains.com/idea/download/ 旧版:https://www.jetbrains.com/idea/dow ...

  3. Java1.8的HashMap源码解析

    java1.8是现在用的最多的版本,hashmap是现在用的最多的map,今天我们试图分析一下源码. 数据结构 首先我们注意到数据是存放在一个Node数组里面 transient Node<K, ...

  4. 别逃避,是时候来给JVM一记重锤了

    今天是猿灯塔“365天原创计划”第2天.   今天讲:   为什么写这个主题呢? 之前看到不少同学在讨论,     今天呢火星哥抽出点时间来帮大家整理一下关于JVM的一些知识点     一.JVM是什 ...

  5. Windows系统VSCode、VBox搭建C/C++开发环境

    好几年没有写过C/C++代码,基本上都忘光了,之前是使用VC++6.0写代码的,最近用VSCode成功搭建了C/C++开发环境,这里记录一下搭建过程. 1. 安装VSCode 在官网https://c ...

  6. NumPy基础知识图谱

    所有内容整理自<利用Python进行数据分析>,使用MindMaster Pro 7.3制作,emmx格式,源文件已经上传Github,需要的同学转左上角自行下载.该图谱只是NumPy的基 ...

  7. 基于SpringBoot AOP面向切面编程实现Redis分布式锁

    基于SpringBoot AOP面向切面编程实现Redis分布式锁 基于SpringBoot AOP面向切面编程实现Redis分布式锁 基于SpringBoot AOP面向切面编程实现Redis分布式 ...

  8. Linux系统安装JDK8

    一.卸载现用的JDK 1.查看Linux自带的JDK是否已安装 查看是否安装openjdk,java  -version (yum安装的 一般都是 OpenJDK     命令:yum install ...

  9. C++各种格式转换

    int main() {     stringstream sstr;     //--------int转string-----------     int a=100;     string st ...

  10. C#使用NPOI对Word文档进行导出操作的dll最新版2.5.1

    Npoi导出非模板 最近使用NPOI做了个导出Word文档的功能,因为之前都是导出Excel很方便(不用模板),所以导出Word也选用了Npoi(也没有用模板,