消息队列及四大主流MQ的优缺点


消息队列及四大主流MQ的优缺点


正文

引子

先想几个问题:

  • 为什么要使用MQ
  • 消息队列有什么优点和缺点
  • kafka、ActiveMQ、RabbitMQ、RocketMQ有什么区别

为什么要使用MQ

MQ的使用场景有很多,但是比较核心的就是:解耦、异步、削锋。

系统解耦

首先举例下面这个场景,现有ABCDE五个系统,最初的时候BCD三个系统都要调用A系统的接口获取数据,一切都很正常, 但是突然,D系统说:我不要了,你不用给我传数据了,A系统无奈,只能修改代码,将调用D系统的代码删除, 这时候还没删除呢,E系统发送了请求,但是A系统这时候还没处理完D系统的请求,A系统卒!

上述场景中,BCDE都需要用到A系统提供的数据,A系统跟其他四个系统严重耦合,需要时时刻刻考虑其他四个系统要是挂了怎么办, 需不需要重新发送数据给他们,这个时候的A系统内心是崩溃的。

但是如果使用了MQ之后 ,A系统的数据只需要放到MQ里面,其他的系统想请求获取数据只需要去MQ里面消费即可, 如果突然不想请求了,就取消对MQ的消费就行了,A系统根本不需要考虑给谁去响应这个数据,也不需要去维护代码, 也不用考虑其他系统是否调用成功,失败超时等情况。

总结:通过MQ发布订阅消息的模型,A系统就成功的跟其他系统解耦了。

异步调用

场景二,还是ABCD四个系统,A系统收到一个请求,需要在自己本地写库,还需要往BCD三个系统写库,A系统自己写本地库需要3ms, 往其他系统写库相对较慢,B系统200ms ,C系统350ms,D系统400ms,这样算起来, 整个功能从请求到响应的时间为3ms+200ms+350ms+400ms=953ms,接近一秒,对于用户来说, 点个按钮要等这么长时间,基本是无法接受的。

一般的互联网企业,对于用户请求响应的时间要求在100ms-200ms之间,这样,用户的眼睛存在视觉暂停现象, 用户响应时间在此范围内就可以了,所以上面的现象是不可取的。

如果用了MQ,用户发送请求到A系统耗时3ms,A系统发送三条消息到MQ,假如耗时5ms, 用户从发送请求到相应3ms+5ms=8ms,仅用了8ms,用户的体验非常好。

流量削峰

场景三,这次举个实例吧,也是近期发生的,我们都知道 ,2020年爆发的这场新冠病毒,导致各大线上商城APP里面的口罩被抢购一空, 在这种情况下,JD商城开启了一场每晚八点的抢购3Q口罩的活动,每天下午三点进行预约,晚上八点抢购,从JD商城刚上线这个活动, 我连续抢了近一个周,也算是见证了一个百万并发量系统从出现问题到完善的一个过程,最初第一天,我抢购的时候,一百多万预约, 到八点抢购估计也能有百万的并发量,可是第一天,到八点我抢的时候,由于并发量太高,直接把JD服务器弄崩了,直接报了异常, 可能JD在上线这个活动的时候也没能够想到会有那么高的并发,打了一个猝不及防,但是这只是在前一两天出现报异常的情况, 后面却没有再出现异常信息,到后来再抢购只是响应的时间变得很慢,但是JD系统并没有崩溃, 这种情况下一般就是用了MQ(或者之前用了MQ,这次换了个吞吐量级别更高的MQ),也正是利用了MQ的三大好处之一——削峰。

JD系统每天0—19点,系统风平浪静,结果一到20点抢购的时候,每秒并发达到百万, 假设JD数据库没秒能处理1.5w条并发请求(并非实际数据,主要为了举例),到20点抢购的时候,每秒并发百万, 这直接导致系统异常,但是20点一过,可能也就几万用户在线操作,每秒的请求可能也就几百条,对整个系统毫无压力。

用户 -> 系统 -> 数据库

如果使用了MQ,每秒百万个请求写入MQ,因为JD系统每秒能处理1W+的请求,JD系统处理完然后再去MQ里面,再拉取1W+的请求处理, 每次不要超过自己能处理的最大请求量就ok,这样下来,等到20点高峰期的时候,系统也不会挂掉,但是近一个小时内, 系统处理请求的速度是肯定赶不上用户的并发请求的,所以都会积压在MQ中,甚至可能积压千万条,但是高峰期过后, 每秒只会有一千多的并发请求进入MQ,但是JD系统还是会以每秒1W+的速度处理请求,所以高峰期一过, JD系统会很快消化掉积压在MQ的请求,在用户那边可能也就是等的时间长一点,但是绝对不会让系统挂掉。

消息队列的优缺点

优点

上面已经说过了,系统解耦,异步调用,流量削峰。

缺点

  1. 系统可用性降低: 系统引入的外部依赖越多,系统要面对的风险越高,拿场景一来说,本来ABCD四个系统配合的好好的,没啥问题, 但是你偏要弄个MQ进来插一脚,虽然好处挺多,但是万一MQ挂掉了呢,那样你系统不也就挂掉了。
  2. 系统复杂程度提高: 非要加个MQ进来,如何保证没有重复消费呢?如何处理消息丢失的情况?怎么保证消息传递的顺序?问题太多。
  3. 一致性的问题: A系统处理完再传递给MQ就直接返回成功了,用户以为你这个请求成功了, 但是,如果在BCD的系统里,BC两个系统写库成功,D系统写库失败了怎么办,这样就导致数据不一致了。

所以,消息队列其实是一套非常复杂的架构,你在享受MQ带来的好处的同时,也要做各种技术方案把MQ带来的一系列的问题解决掉, 等一切都做好之后,系统的复杂程度硬生生提高了一个等级。

四大主流MQ各自的优缺点

目前业界四大主流的MQ有kafka、ActiveMQ、RabbitMQ、RocketMQ。

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

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

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

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

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






参考资料

详解MQ消息队列及四大主流MQ的优缺点 https://mp.weixin.qq.com/s/0bhyOBKRYhGBme8gTV40Qw

消息队列:消息可靠性、重复消息、消息积压、利用消息实现分布式事务 https://mp.weixin.qq.com/s?__biz=MzIzODIzNzE0NQ==&mid=2654440578&idx=1&sn=b26b5068764babc67f2502bfc7043c85&chksm=f2ff4834c588c122f3e90784478aac0c2088e7003716738803191ebd5dea84f217bca608c87b&scene=132#wechat_redirect


返回