美文网首页
面试之消息队列三大问

面试之消息队列三大问

作者: Looveh | 来源:发表于2019-01-10 11:18 被阅读0次

    原文地址:https://github.com/doocs/advanced-java/blob/master/docs/high-concurrency/why-mq.md

    • 为什么使用消息队列

    • 消息队列的优缺点

    • Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什么区别,以及适合哪些场景?

    解析

    为什么使用消息队列

    首先知道一般什么业务场景下使用消息队列?

    3个常用场景 解耦、异步、削峰

    解耦

    场景:A调用B、C、D三个服务,如果E也要或者D不要了,就得修改A系统的代码。如果你是A,你会不会崩溃?



    在这个系统中,系统A和其他系统严重耦合,很多系统都需要A的数据,但是如果某个系统挂了呢?要不要重发?要不要把消息存起来?A又崩溃了。。。。
    如果使用MQ,A发送一条消息,直接存到MQ里面。哪个系统需要就自己去MQ里面取。哪个系统不要了,自己取消消费就行。A根本不需要考虑发给谁,也不需要考虑人家是否成功或失败超时等情况。


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

    异步

    场景:A接收到一个请求,需要在本地写库,并且还要在B、C、D三个服务写库,假如本地写库需要3ms,B写库300ms,C写库需要450ms,D写库需要200ms,这时请求用时为3+300+450+200将近1s。用户觉得一个请求需要一秒钟,根本接收不了。


    如果使用MQ,那么A系统将发送3条消息到MQ,假如用时5ms,A从用户接收到一个请求到返回才用了3 + 5 = 8ms,对于用户而言,哇!这个网站好快啊!做的真好。


    削峰

    假如一个系统,A系统在0:00-12:00这个时间段内的请求每秒并发数为50。但是一到12:00-13:00这个时间段内,A系统的请求每秒并发数飙升,直接飙升到5K,但是系统是直接基于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 倍。但是关键时刻,用,还是得用的。

    Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什么优缺点?

    特性 ActiveMQ RabbitMQ RocketMQ Kafka
    单机吞吐量 万级,比 RocketMQ、Kafka 低一个数量级 同 ActiveMQ 10 万级,支撑高吞吐 10 万级,高吞吐,一般配合大数据类的系统来进行实时数据计算、日志采集等场景
    topic 数量对吞吐量的影响 topic 可以达到几百/几千的级别,吞吐量会有较小幅度的下降,这是 RocketMQ 的一大优势,在同等机器下,可以支撑大量的 topic topic 从几十到几百个时候,吞吐量会大幅度下降,在同等机器下,Kafka 尽量保证 topic 数量不要过多,如果要支撑大规模的 topic,需要增加更多的机器资源
    时效性 ms 级 微秒级,这是 RabbitMQ 的一大特点,延迟最低 ms 级 延迟在 ms 级以内
    可用性 高,基于主从架构实现高可用 同 ActiveMQ 非常高,分布式架构 非常高,分布式,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用
    消息可靠性 有较低的概率丢失数据 基本不丢 经过参数优化配置,可以做到 0 丢失 同 RocketMQ
    功能支持 MQ 领域的功能极其完备 基于 erlang 开发,并发能力很强,性能极好,延时很低 MQ 功能较为完善,还是分布式的,扩展性好 功能较为简单,主要支持简单的 MQ 功能,在大数据领域的实时计算以及日志采集被大规模使用

    综上,各种对比之后,有如下建议:

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

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

    不过现在确实越来越多的公司,会去用 RocketMQ,确实很不错(阿里出品),但社区可能有突然黄掉的风险,对自己公司技术实力有绝对自信的,推荐用 RocketMQ,否则回去老老实实用 RabbitMQ 吧,人家有活跃的开源社区,绝对不会黄。

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

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

    相关文章

      网友评论

          本文标题:面试之消息队列三大问

          本文链接:https://www.haomeiwen.com/subject/klmorqtx.html