为什么使用消息队列啊?消息队列有什么优点和缺点啊?kafka、activemq、rabbitmq、rocketmq都有什么区别以及适合哪些场景?_rabbitmq消息队列的作用-程序员宅基地

技术标签: 中间件  rabbitmq  

1、

为什么使用消息队列啊?消息队列有什么优点和缺点啊?kafka、activemq、rabbitmq、rocketmq都有什么区别以及适合哪些场景?

 

(1)第一,你知道不知道你们系统里为什么要用消息队列这个东西?

 

项目里用了redis、mq,但是其实他并不知道自己为什么要用这个东西。其实说白了,就是为了用而用,或者是别人设计的架构,他从头到尾没思考过。

 

没有对自己的架构问过为什么的人,一定是平时没有思考的人,面试官对这类候选人印象通常很不好。

(2)第二,你既然用了消息队列这个东西,你知道不知道用了有什么好处?

系统中引入消息队列之后会不会有什么坏处?你要是没考虑过这个,那你盲目弄个MQ进系统里,后面出了问题你是不是就自己溜了给公司留坑?你要是没考虑过引入一个技术可能存在的弊端和风险,面试官把这类候选人招进来了,基本可能就是挖坑型选手。

(3)第三,既然你用了MQ,可能是某一种MQ,那么你当时做没做过调研啊?

 

你别傻乎乎的自己拍脑袋看个人喜好就瞎用了一个MQ,比如kafka。甚至都从没调研过业界到底流行的MQ有哪几种?每一个MQ的优点和缺点是什么?每一个MQ没有绝对的好坏,但是就是看用在哪个场景可以扬长避短,利用其优势,规避其劣势。

 

如果是一个不考虑技术选型的候选人招进了团队,面试官交给他一个任务,去设计个什么系统,他在里面用一些技术,可能都没考虑过选型,最后选的技术可能并不一定合适,一样是留坑

 

什么使用消息队列

其实就是问问你消息队列都有哪些使用场景,然后你项目里具体是什么场景,说说你在这个场景里用消息

队列是什么?

期望的一个回答是说,你们公司有个什么业务场景,这个业务场景有个什么技术挑战,如果不用 MQ 可能会很麻烦,但是你现在用了 MQ 之后带给了你很多的好处。

先说一下消息队列常见的使用场景吧,其实场景有很多,但是比较核心的有 3 个:解耦、异步、削峰

解耦

看这么个场景。A 系统发送数据到 BCD 三个系统,通过接口调用发送。如果 E 系统也要这个数据呢?那如果 C 系统现在不需要了呢?A 系统负责人几乎崩溃......

在这个场景中,A 系统跟其它各种乱七八糟的系统严重耦合,A 系统产生一条比较关键的数据,很多系统都需要 A 系统将这个数据发送过来。A 系统要时时刻刻考虑 BCDE 四个系统如果挂了该咋办?要不要重发,要不要把消息存起来?头发都白了啊!

如果使用 MQ,A 系统产生一条数据,发送到 MQ 里面去,哪个系统需要数据自己去 MQ 里面消费。如果新系统需要数据,直接从 MQ 里消费即可;如果某个系统不需要这条数据了,就取消对 MQ 消息的消费即可。这样下来,A 系统压根儿不需要去考虑要给谁发送数据,不需要维护这个代码,也不需要考虑人家是否调用成功、失败超时等情况。

 

总结:通过一个 MQ,Pub/Sub 发布订阅消息这么一个模型,A 系统就跟其它系统彻底解耦了。

你需要去考虑一下你负责的系统中是否有类似的场景,就是一个系统或者一个模块,调用了多个系统或者模块,互相之间的调用很复杂,维护起来很麻烦。但是其实这个调用是不需要直接同步调用接口的,如果用 MQ 给它异步化解耦,也是可以的,你就需要去考虑在你的项目里,是不是可以运用这个 MQ去进行系统的解耦。在简历中体现出来这块东西,用 MQ 作解耦。

异步

再来看一个场景,A 系统接收一个请求,需要在自己本地写库,还需要在 BCD 三个系统写库,自己本地写库要 3ms,BCD 三个系统分别写库要 300ms、450ms、200ms。最终请求总延时是 3 + 300 + 450 + 200 = 953ms,接近 1s,用户感觉搞个什么东西,慢死了慢死了。用户通过浏览器发起请求,等待个 1s,这几乎是不可接受的。

一般互联网类的企业,对于用户直接的操作,一般要求是每个请求都必须在 200 ms 以内完成,对用户几乎是无感知的。

如果使用 MQ,那么 A 系统连续发送 3 条消息到 MQ 队列中,假如耗时 5ms,A 系统从接受一个请求到返回响应给用户,总时长是 3 + 5 = 8ms,对于用户而言,其实感觉上就是点个按钮,8ms 以后就直接返回了,爽!网站做得真好,真快!

削峰

每天 0:00 到 12:00,A 系统风平浪静,每秒并发请求数量就 50 个。结果每次一到 12:00 ~ 13:00 ,每秒并发请求数量突然会暴增到 5k+ 条。但是系统是直接基于 MySQL 的,大量的请求涌入 MySQL,每秒钟对 MySQL 执行约 5k 条 SQL。

一般的 MySQL,扛到每秒 2k 个请求就差不多了,如果每秒请求到 5k 的话,可能就直接把 MySQL 给打死了,导致系统崩溃,用户也就没法再使用系统了。

但是高峰期一过,到了下午的时候,就成了低峰期,可能也就 1w 的用户同时在网站上操作,每秒中的请求数量可能也就 50 个请求,对整个系统几乎没有任何的压力。

 

如果使用 MQ,每秒 5k 个请求写入 MQ,A 系统每秒钟最多处理 2k 个请求,因为 MySQL 每秒钟最多处理2k 个。A 系统从 MQ 中慢慢拉取请求,每秒钟就拉取 2k 个请求,不要超过自己每秒能处理的最大请求数量就 ok,这样下来,哪怕是高峰期的时候,A 系统也绝对不会挂掉。而 MQ 每秒钟 5k 个请求进来,就 2k个请求出去,结果就导致在中午高峰期(1 个小时),可能有几十万甚至几百万的请求积压在 MQ 中。

这个短暂的高峰期积压是 ok 的,因为高峰期过了之后,每秒钟就 50 个请求进 MQ,但是 A 系统依然会按照每秒 2k 个请求的速度在处理。所以说,只要高峰期一过,A 系统就会快速将积压的消息给解决掉。


消息队列有什么优缺点

优点上面已经说了,就是在特殊场景下有其对应的好处解耦、异步、削峰

缺点有以下几个:

系统可用性降低                                                                                                                                

系统引入的外部依赖越多,越容易挂掉。本来你就是 A 系统调用 BCD 三个系统的接口就好了,人ABCD 四个系统好好的,没啥问题,你偏加个 MQ 进来,万一 MQ 挂了咋整,MQ 一挂,整套系统崩溃的,你不就完了?如何保证消息队列的高可用,可以查看另一篇文章。

系统复杂度提高                                                                                                                                  

 硬生生加个 MQ 进来,你怎么保证消息没有重复消费?怎么处理消息丢失的情况?怎么保证消息传递的顺序性?头大头大,问题一大堆,痛苦不已。

一致性问题                                                                                                                                     

  A 系统处理完了直接返回成功了,人都以为你这个请求就成功了;但是问题是,要是 BCD 三个系统那里,BD 两个系统写库成功了,结果 C 系统写库失败了,咋整?你这数据就不一致了。

所以消息队列实际是一种非常复杂的架构,你引入它有很多好处,但是也得针对它带来的坏处做各种额外的技术方案和架构来规避掉,做好之后,你会发现,妈呀,系统复杂度提升了一个数量级,也许是复杂了 10倍。但是关键时刻,用,还是得用的。

 

 

 

 

(3)kafka、activemq、rabbitmq、rocketmq都有什么优点和缺点啊?

 

常见的MQ其实就这几种,别的还有很多其他MQ,但是比较冷门的,那么就别多说了

 

作为一个码农,你起码得知道各种mq的优点和缺点吧,咱们来画个表格看看

 

 

 

特性

ActiveMQ

RabbitMQ

RocketMQ

Kafka

单机吞吐量

万级,吞吐量比RocketMQ和Kafka要低了一个数量级

万级,吞吐量比RocketMQ和Kafka要低了一个数量级

10万级,RocketMQ也是可以支撑高吞吐的一种MQ

10万级别,这是kafka最大的优点,就是吞吐量高。

 

一般配合大数据类的系统来进行实时数据计算、日志采集等场景

topic数量对吞吐量的影响

 

 

topic可以达到几百,几千个的级别,吞吐量会有较小幅度的下降

 

这是RocketMQ的一大优势,在同等机器下,可以支撑大量的topic

topic从几十个到几百个的时候,吞吐量会大幅度下降

 

所以在同等机器下,kafka尽量保证topic数量不要过多。如果要支撑大规模topic,需要增加更多的机器资源

时效性

ms级

微秒级,这是rabbitmq的一大特点,延迟是最低的

ms级

延迟在ms级以内

可用性

高,基于主从架构实现高可用性

高,基于主从架构实现高可用性

非常高,分布式架构

非常高,kafka是分布式的,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用

消息可靠性

有较低的概率丢失数据

 

经过参数优化配置,可以做到0丢失

经过参数优化配置,消息可以做到0丢失

功能支持

MQ领域的功能极其完备

基于erlang开发,所以并发能力很强,性能极其好,延时很低

MQ功能较为完善,还是分布式的,扩展性好

功能较为简单,主要支持简单的MQ功能,在大数据领域的实时计算以及日志采集被大规模使用,是事实上的标准

优劣势总结

非常成熟,功能强大,在业内大量的公司以及项目中都有应用

 

偶尔会有较低概率丢失消息

 

而且现在社区以及国内应用都越来越少,官方社区现在对ActiveMQ 5.x维护越来越少,几个月才发布一个版本

 

而且确实主要是基于解耦和异步来用的,较少在大规模吞吐的场景中使用

 

erlang语言开发,性能极其好,延时很低;

 

吞吐量到万级,MQ功能比较完备

 

而且开源提供的管理界面非常棒,用起来很好用

 

社区相对比较活跃,几乎每个月都发布几个版本分

 

在国内一些互联网公司近几年用rabbitmq也比较多一些

 

但是问题也是显而易见的,RabbitMQ确实吞吐量会低一些,这是因为他做的实现机制比较重。

 

而且erlang开发,国内有几个公司有实力做erlang源码级别的研究和定制?如果说你没这个实力的话,确实偶尔会有一些问题,你很难去看懂源码,你公司对这个东西的掌控很弱,基本职能依赖于开源社区的快速维护和修复bug。

 

而且rabbitmq集群动态扩展会很麻烦,不过这个我觉得还好。其实主要是erlang语言本身带来的问题。很难读源码,很难定制和掌控。

接口简单易用,而且毕竟在阿里大规模应用过,有阿里品牌保障

 

日处理消息上百亿之多,可以做到大规模吞吐,性能也非常好,分布式扩展也很方便,社区维护还可以,可靠性和可用性都是ok的,还可以支撑大规模的topic数量,支持复杂MQ业务场景

 

而且一个很大的优势在于,阿里出品都是java系的,我们可以自己阅读源码,定制自己公司的MQ,可以掌控

 

社区活跃度相对较为一般,不过也还可以,文档相对来说简单一些,然后接口这块不是按照标准JMS规范走的有些系统要迁移需要修改大量代码

 

还有就是阿里出台的技术,你得做好这个技术万一被抛弃,社区黄掉的风险,那如果你们公司有技术实力我觉得用RocketMQ挺好的

kafka的特点其实很明显,就是仅仅提供较少的核心功能,但是提供超高的吞吐量,ms级的延迟,极高的可用性以及可靠性,而且分布式可以任意扩展

 

同时kafka最好是支撑较少的topic数量即可,保证其超高吞吐量

 

而且kafka唯一的一点劣势是有可能消息重复消费,那么对数据准确性会造成极其轻微的影响,在大数据领域中以及日志采集中,这点轻微影响可以忽略

 

这个特性天然适合大数据实时计算以及日志收集

 

 

综上所述,各种对比之后,我个人倾向于是:

 

一般的业务系统要引入MQ,最早大家都用ActiveMQ,但是现在确实大家用的不多了,没经过大规模吞吐量场景的验证,社区也不是很活跃,所以大家还是算了吧,我个人不推荐用这个了;

 

后来大家开始用RabbitMQ,但是确实erlang语言阻止了大量的java工程师去深入研究和掌控他,对公司而言,几乎处于不可控的状态,但是确实人是开源的,比较稳定的支持,活跃度也高;

 

不过现在确实越来越多的公司,会去用RocketMQ,确实很不错,但是我提醒一下自己想好社区万一突然黄掉的风险,对自己公司技术实力有绝对自信的,我推荐用RocketMQ,否则回去老老实实用RabbitMQ吧,人是活跃开源社区,绝对不会黄

 

所以中小型公司,技术实力较为一般,技术挑战不是特别高,用RabbitMQ是不错的选择;大型公司,基础架构研发实力较强,用RocketMQ是很好的选择

 

如果是大数据领域的实时计算、日志采集等场景,用Kafka是业内标准的,绝对没问题,社区活跃度很高,绝对不会黄,何况几乎是全世界这个领域的事实性规范

 

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/liuerchong/article/details/107767440

智能推荐

TOEFL写作——独立写作段落拓展-程序员宅基地

文章浏览阅读156次。功能 常用单词、短语 表示列举 For example, / For instance, / Take ... as an example. We might take .. for example / as an example. A case in point is (that) ... 分析 unsurprisingly in this case...

值得学习的C语言开源项目-程序员宅基地

文章浏览阅读170次。转载自https://blog.csdn.net/a493203176/article/details/79195454值得学习的C语言开源项目-1. WebbenchWebbench是一个在linux下使用的非常简单的网站压测工具。它使用fork()模拟多个客户端同时访问我们设定的URL,测试网站在压力下工作的性能,最多可以模拟3万个并发连接去测试网站的负载能力。Webbench使用...

Sqlite3 数据库基本操作_-lsqlite3-程序员宅基地

文章浏览阅读1w次,点赞19次,收藏173次。Sqlite3 数据库基本操作1、sqlite3命令**2、sqlite3编程接口:**3、事务:一个或多个更改数据库的扩展4、like和glob子句:5、limit 和 offset6、having:7、distinct8、约束:9、内连接10、别名11、触发器12. 索引1、sqlite3命令1.打开数据库: sqlite3 <*.db>2.系统命令: 以’.'开头 .quit : 退出sqlite3 .help : 查看帮助文档 .database: 显示当前打开的数据库_-lsqlite3

MapReduce当中Partitioner的用法_简述mapreduce中,partitioner 如何使用-程序员宅基地

文章浏览阅读277次。Partitioner的用法:防盗版实名手机尾号:73203。如果现在我们的需求变成,输出放在两个文件当中,按照关键字的首个字母的26个字母来分,头13个放在一个文件当中,以此类推, 这时我们就要用到partition的技术。package com;import java.io.IOException;import java.util.StringTokenizer;import org..._简述mapreduce中,partitioner 如何使用

Google Earth Engine(GEE)对指定地点Sentinel-2 Level1C数据进行NDVI指数的计算_gee计算区域栅格尺度ndvi 哨兵-程序员宅基地

文章浏览阅读4k次,点赞5次,收藏55次。Google Earth Engine (GEE) 是由谷歌公司开发的众多应用之一。借助谷歌公司超强的服务器运算能力以及与NASA的合作关系,GEE平台将Landsat/Sentinel等可以公开获取的遥感图像数据存储在谷歌的磁盘阵列中,使得GEE用户可以方便的提取、调用和分析海量的遥感大数据资源。本文基于GEE平台,实现对指定地点Sentinel-2 Level1C数据进行NDVI指数的计算,示例地点为湖南省长沙市。代码如下:(JS)var cs = China.filterBound._gee计算区域栅格尺度ndvi 哨兵

JQUERY自定义下拉单选加可输入的SELECT_jquery selectpage 自定义输入-程序员宅基地

文章浏览阅读1.2k次。本文将介绍一个使用JQUERY实现的一个自定义下拉单选框ton_jquery selectpage 自定义输入

随便推点

composer install报错_failed to install packages, calc composer.json has-程序员宅基地

文章浏览阅读1.7k次。执行composer install遇到错误:Your requirements could not be resolved to an installable set of packages.这是因为不匹配composer.json要求的版本。提示我的PHP 7版本太高,不符合composer.json需要的版本,但是在PHP 7下应该也是可以运行的,composer可以设置忽略版本匹配,命令是:composer install --ignore-platform-reqs # or comp._failed to install packages, calc composer.json hash value fail

微信小程序 - 实现简单登录和个人信息页面_小程序最新个人信息展示-程序员宅基地

文章浏览阅读3.5w次,点赞76次,收藏661次。接上节简单介绍完wxml,这节实际运用小程序的wxml来实现一套简单登录和个人信息展示。登录页面创建好项目后,在pages下新建一个login目录,右键login文件夹,选择新建page,创建login的page,如下图:创建后的page如下图:创建好login page后,项目会自动在app.js中添加login的page路劲,新增的page会顺序加在后边,小程序打开默认加载第一个路径,我们将login的路径移到最前边,这样每次编译后,初始化页面就为登录的页面了,如下..._小程序最新个人信息展示

使用Mathematica绘制笛卡尔叶形线图形(Folium of Descartes)_mathematica向量做笛卡尔-程序员宅基地

文章浏览阅读5.5k次。“著名科学家笛卡儿,根据他所研究的一簇花瓣和叶形曲线特征,列出了x^3+y^3-3axy=0的方程式,这就是现代数学中有名的“笛卡儿叶线”(或者叫“叶形线”),数学家还为它取了一个诗意的名字——茉莉花瓣曲线。”这个看似简单的图形在Mathematica却不是那么好画,试了半天没成功,参考了这篇文章才画出来:http://community.wolfram.com/groups/-/m/t/1044..._mathematica向量做笛卡尔

Execution failed for task ':app:mergeDebugResources'-程序员宅基地

文章浏览阅读2.2w次。(Error:Execution failed for task ':app:mergeDebugResources'.> Some file crunching failed, see logs for details)_execution failed for task ':app:mergedebugresources'.

JSONPath的基础使用_jsonpath.eval-程序员宅基地

文章浏览阅读6k次,点赞2次,收藏14次。JSONPath可以快速提取json固定位置、范围的数据,而不需要创建单独的JSONObject对象。但如果每次处理的json数据格式会改变,则该方式不太适用。_jsonpath.eval

asp.net页面中Menu控件下拉菜单被frame挡住和iframe自适应高度的解决办法-程序员宅基地

文章浏览阅读155次。当你在做一个仿windows程序的顶部菜单框架的时候,在asp.net中你可能会使用两个frame,一个frame在上面用来放菜单一个frame在下面用来方菜单点击后打开的页面.页面实现很简单,单运行的时候你就发现放菜单的那个frame将菜单的下列菜单在挡住根本伸不到下面的frame中.解决被挡住的问题是不能使用frame,做法是在一个单独的asp.net页面中放一个menu 和一个if..._asp:menu超出iframe如何解决

推荐文章

热门文章

相关标签