架构-到底什么时候该使用MQ【转】
点击:《查看原文》
一、缘起
一切脱离业务的架构设计与新技术引入都是耍流氓。
引入一个技术之前,首先应该解答的问题是,这个技术解决什么问题。
就像微服务分层架构之前,应该首先回答,为什么要引入微服务,微服务究竟解决什么问题(详见《互联网架构为什么要做微服务?》)。
最近分享了几篇MQ相关的文章:
不少网友询问,究竟什么时候使用MQ,MQ究竟适合什么场景,故有了此文。
二、MQ是干嘛的
消息总线(Message Queue),后文称MQ,是一种跨进程的通信机制,用于上下游传递消息。
在互联网架构中,MQ是一种非常常见的上下游“逻辑解耦+物理解耦”的消息通信服务。
使用了MQ之后,消息发送上游只需要依赖MQ,逻辑上和物理上都不用依赖其他服务。
三、什么时候不使用消息总线
既然MQ是互联网分层架构中的解耦利器,那所有通讯都使用MQ岂不是很好?这是一个严重的误区,调用与被调用的关系,是无法被MQ取代的。
MQ的不足是:
1)系统更复杂,多了一个MQ组件
2)消息传递路径更长,延时会增加
3)消息可靠性和重复性互为矛盾,消息不丢不重难以同时保证
4)上游无法知道下游的执行结果,这一点是很致命的
举个栗子:用户登录场景,登录页面调用passport服务,passport服务的执行结果直接影响登录结果,此处的“登录页面”与“passport服务”就必须使用调用关系,而不能使用MQ通信。
无论如何,记住这个结论:调用方实时依赖执行结果的业务场景,请使用调用,而不是MQ。
四、什么时候使用MQ
【典型场景一:数据驱动的任务依赖】
什么是任务依赖,举个栗子,互联网公司经常在凌晨进行一些数据统计任务,这些任务之间有一定的依赖关系,比如:
1)task3需要使用task2的输出作为输入
2)task2需要使用task1的输出作为输入
这样的话,tast1, task2, task3之间就有任务依赖关系,必须task1先执行,再task2执行,载task3执行。
对于这类需求,常见的实现方式是,使用cron人工排执行时间表:
1)task1,0:00执行,经验执行时间为50分钟
2)task2,1:00执行(为task1预留10分钟buffer),经验执行时间也是50分钟
3)task3,2:00执行(为task2预留10分钟buffer)
这种方法的坏处是:
1)如果有一个任务执行时间超过了预留buffer的时间,将会得到错误的结果,因为后置任务不清楚前置任务是否执行成功,此时要手动重跑任务,还有可能要调整排班表
2)总任务的执行时间很长,总是要预留很多buffer,如果前置任务提前完成,后置任务不会提前开始
3)如果一个任务被多个任务依赖,这个任务将会称为关键路径,排班表很难体现依赖关系,容易出错
4)如果有一个任务的执行时间要调整,将会有多个任务的执行时间要调整
无论如何,采用“cron排班表”的方法,各任务耦合,谁用过谁痛谁知道(采用此法的请评论留言)
优化方案是,采用MQ解耦:
1)task1准时开始,结束后发一个“task1 done”的消息
2)task2订阅“task1 done”的消息,收到消息后第一时间启动执行,结束后发一个“task2 done”的消息
3)task3同理
采用MQ的优点是:
1)不需要预留buffer,上游任务执行完,下游任务总会在第一时间被执行
2)依赖多个任务,被多个任务依赖都很好处理,只需要订阅相关消息即可
3)有任务执行时间变化,下游任务都不需要调整执行时间
需要特别说明的是,MQ只用来传递上游任务执行完成的消息,并不用于传递真正的输入输出数据。
【典型场景二:上游不关心执行结果】
上游需要关注执行结果时要用“调用”,上游不关注执行结果时,就可以使用MQ了。
举个栗子,58同城的很多下游需要关注“用户发布帖子”这个事件,比如招聘用户发布帖子后,招聘业务要奖励58豆,房产用户发布帖子后,房产业务要送2个置顶,二手用户发布帖子后,二手业务要修改用户统计数据。
对于这类需求,常见的实现方式是,使用调用关系:
帖子发布服务执行完成之后,调用下游招聘业务、房产业务、二手业务,来完成消息的通知,但事实上,这个通知是否正常正确的执行,帖子发布服务根本不关注。
这种方法的坏处是:
1)帖子发布流程的执行时间增加了
2)下游服务当机,可能导致帖子发布服务受影响,上下游逻辑+物理依赖严重
3)每当增加一个需要知道“帖子发布成功”信息的下游,修改代码的是帖子发布服务,这一点是最恶心的,属于架构设计中典型的依赖倒转,谁用过谁痛谁知道(采用此法的请评论留言)
优化方案是,采用MQ解耦:
1)帖子发布成功后,向MQ发一个消息
2)哪个下游关注“帖子发布成功”的消息,主动去MQ订阅
采用MQ的优点是:
1)上游执行时间短
2)上下游逻辑+物理解耦,除了与MQ有物理连接,模块之间都不相互依赖
3)新增一个下游消息关注方,上游不需要修改任何代码
典型场景三:上游关注执行结果,但执行时间很长
有时候上游需要关注执行结果,但执行结果时间很长(典型的是调用离线处理,或者跨公网调用),也经常使用回调网关+MQ来解耦。
举个栗子,微信支付,跨公网调用微信的接口,执行时间会比较长,但调用方又非常关注执行结果,此时一般怎么玩呢?
一般采用“回调网关+MQ”方案来解耦:
1)调用方直接跨公网调用微信接口
2)微信返回调用成功,此时并不代表返回成功
3)微信执行完成后,回调统一网关
4)网关将返回结果通知MQ
5)请求方收到结果通知
这里需要注意的是,不应该由回调网关来调用上游来通知结果,如果是这样的话,每次新增调用方,回调网关都需要修改代码,仍然会反向依赖,使用回调网关+MQ的方案,新增任何对微信支付的调用,都不需要修改代码啦。
五、总结
MQ是一个互联网架构中常见的解耦利器。
什么时候不使用MQ?
上游实时关注执行结果
什么时候使用MQ?
1)数据驱动的任务依赖
2)上游不关心多下游执行结果
3)异步返回执行时间长
架构-到底什么时候该使用MQ【转】的更多相关文章
- 终极对决!Dubbo 和 Spring Cloud 微服务架构到底孰优孰劣
标签: 微服务dubbospring架构 前言 微服务架构是互联网很热门的话题,是互联网技术发展的必然结果.它提倡将单一应用程序划分成一组小的服务,服务之间互相协调.互相配合,为用户提供最终价值.虽然 ...
- 到底什么时候该使用MQ?
一.缘起 一切脱离业务的架构设计与新技术引入都是耍流氓. 引入一个技术之前,首先应该解答的问题是,这个技术解决什么问题. 就像微服务分层架构之前,应该首先回答,为什么要引入微服务,微服务究竟解决什么问 ...
- 【转】到底什么时候应该用MQ
原文地址:http://zhuanlan.51cto.com/art/201704/536407.htm 一.缘起 一切脱离业务的架构设计与新技术引入都是耍流氓. 引入一个技术之前,首先应该解答的问题 ...
- 170317、到底什么时候该使用MQ?
一.缘起 一切脱离业务的架构设计与新技术引入都是耍流氓. 引入一个技术之前,首先应该解答的问题是,这个技术解决什么问题. 就像微服务分层架构之前,应该首先回答,为什么要引入微服务,微服务究竟解决什么问 ...
- 为什么要使用MQ和到底什么时候要使用MQ
一.缘起 一切脱离业务的架构设计与新技术引入都是耍流氓. 引入一个技术之前,首先应该解答的问题是,这个技术解决什么问题. 就像微服务分层架构之前,应该首先回答,为什么要引入微服务,微服务究竟解决什 ...
- mvc和三层架构到底有什么区别
原文地址:http://zhidao.baidu.com/question/82001542.html?qbl=relate_question_3&word=MVC%20%CA%FD%BE%D ...
- Serverless 架构到底要不要服务器?
作者 | aoho 来源 | Serverless 公众号 Serverless 是什么? Serverless 架构是不是就不要服务器了?回答这个问题,我们需要了解下 Serverless 是什么. ...
- MQ(转)
1. 到底什么时候该使用MQ? 1). 典型场景一:数据驱动的任务依赖 采用MQ的优点是: a. 不需要预留buffer,上游任务执行完,下游任务总会在第一时间被执行 b. 依赖多个任务,被多个任务依 ...
- mq使用场景、不丢不重、时序性
mq使用场景.不丢不重.时序性.削峰 参考: http://zhuanlan.51cto.com/art/201704/536407.htm http://zhuanlan.51cto.com/art ...
随机推荐
- SpringBoot-Mybatis_Plus学习记录之公共字段自动填充
一.应用场景 平时在建对象表的时候都会有最后修改时间,最后修改人这两个字段,对于这些大部分表都有的字段,每次在新增和修改的时候都要考虑到这几个字段有没有传进去,很麻烦.mybatisPlus有一个很好 ...
- .Net程序员玩转Android开发--ListView单击事件
public class ListViewClickActivity extends Activity { private ListView lv; SimpleAdap ...
- C# 播放铃声最简短的代码实现方式
因为只是做一个软件的闹铃播放效果,到网上找的时候试了几种,哎,都失败了,而且代码挺杂的,最终一句搞定了: 1 // 窗体加载事件 2 private void Time ...
- ODBC更新记录集提示”记录集为只读“
创建的ODBC应用程序默认的记录集不具有只读属性,但是再更新记录表时会提示”记录集为只读“,这是为什么呢? 今天看书找到了答案: 因为MFC中的数据库类不支持需要连接两个或者多个表的记录集更新,如果选 ...
- Android -- ConditionVariable
线程操作经常用到wait和notify,用起来稍显繁琐,而Android给我们封装好了一个ConditionVariable类,用于线程同步.提供了三个方法block().open().close() ...
- Android -- 系统和自定义Notification
Notification是一种让你的应用程序在不使用Activity的情况下警示用户,Notification是看不见的程序组件警示用户有需要注意的事件发生的最好途径. 作为UI部分,Notifica ...
- JAVA-Eclipse中web-inf和meta-inf文件夹
WEB-INF /WEB-INF/web.xml 你的Web应用程序配置文件,这是一个XML文件,其中描述了 servlet 和其他的应用组件配置及命名规则: /WEB- IN ...
- 自己理解BFC 和 stack context , stack order
1. stack order 发生在BFC计算好了之后. 2.一个一个的BFC里面,不同的block 里面的stack context 会根据 stack order的顺序,进行堆叠.呈现互相遮盖的效 ...
- thinkcmf 角色授权支持分类
ThinkCMF中的权限是以后台菜单为基础来进行设置的(menu table),即如果你需要一个自定义的权限,那么你需要在后台菜单里添加一项菜单,然后在角色管理里可以针对角色进行授权 而现在遇到一 ...
- unity3d内存管理坑爹之处
Resources.UnloadUnusedAssets();会卸载没有引用的资源,切场景也会自动清理 但是注意,如果不调,是不会自动清理的,比如不断的用www加载图片资源,即使没有引用,也一样在内存 ...