先摘一下百度百科的概念:
MQ(Message Queue)消息队列,是基础数据结构中
先进先出
的一种数据结构。一般用来解决应用解耦,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性架构。
主要的MQ产品包括:RabbitMQ、RocketMQ、ZeroMQ、Kafka、IBM WebSphere 等。
MQ 的主要作用嘛,其实基本大家都知道,为了凑点篇幅,我还是列一下:
在一个业务需要多个模块共同实现,或者一条消息有多个系统需要对应处理的时候;只需要主业务完成以后,发送一条消息到 MQ,其余模块消费 MQ 消息,即可实现业务,降低模块之间的耦合。
这个其实是大多是MQ主要的功能之一,将消息发送方和接收方隔离。
主业务执行结束后从属业务通过 MQ,异步执行,减低业务的响应时间,提高用户体验。
相比于传统的串行、并行方式,提高了系统吞吐量。
高并发情况下,业务异步处理,提供高峰期业务处理能力,避免系统瘫痪。
在访问量剧增的情况下,应用仍然需要继续发挥作用,但是这样的突发流量并不常见;如果为以能处理这类峰值访问为标准来投入资源随时待命无疑是巨大的浪费。使用MQ能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷的请求而完全崩溃。
还是以订单系统和结算系统场景为例,如果订单系统通过RPC框架来调用结算系统,在有高峰促销的情况下生成订单的量会非常大,而且由于生成订单的速度也非常快,这样势必会给结算系统造成系统压力,服务器利用率则会偏高,但在不是高峰的时间点订单量比较小,结算系统的服务器利用率则会偏低。对于结算系统来说就会出现下面这样的高峰波谷现象图。
那么如果通过MQ的方式,将订单存储到MQ队列中,消费端通过拉取的方式,并且拉去速度有消费端来控制,则就可以控制流量趋于平稳。这样对于结算系统来讲,就达到了削峰填谷的目的。或者说起到了流控的目标
有些情况下,处理数据的过程会失败。除非数据被持久化,否则将造成丢失。
MQ 把数据进行类持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险。
许多MQ所采用的 “插入-获取-删除” 范式中,在把一个消息从队列中删除之前,需要你的处理系统明确的指出该消息已经被处理完毕,从而确保你的数据被安全的保存直到你使用完毕。
因为 MQ 解耦了你的处理过程,所以增大消息入队和处理的频率是很容易的,只要另外增加处理过程即可。
就比如 DMS 分布式消息服务,不需要改变代码、不需要调节参数。
系统的一部分组件失效时,不会影响到整个系统。
MQ 降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。
在大多使用场景下,数据处理的顺序都很重要。
大部分 MQ 本来就是排序的,并且能保证数据会按照特定的顺序来处理。
在任何重要的系统中,都会有需要不同的处理时间的元素。
例如,加载一张图片比应用过滤器花费更少的时间。消息队列通过一个缓冲层来帮助任务最高效率的执行———写入队列的处理会尽可能的快速。该缓冲有助于控制和优化数据流经过系统的速度。
1、系统可用性降低。使用 MQ 后,许多业务模块依赖 MQ,依赖越多,服务越容易挂掉。需要考虑MQ瘫痪的情况;
2、系统复杂性提高。需要考虑消息丢失、消息重复发送、消息重复消费、消息传递的顺序性、消息积压;
3、业务一致性。如果没有 MQ 有事务保持系统一致性,用了 MQ 以后,A系统保存操作,再向MQ发送消息,B系统成功操作数据库,C系统也成功操作,但是当到D系统时操作失败。再用MQ没有事务的情况下,就导致不一致;
首先要提一句 ActiveMq,已经非常陈旧,社区不活跃,版本更新慢,我看大多数博客都已经不推荐使用了。所以就不纳入考虑范围了。
然后介绍下本次比赛的参赛选手:
RabbitMQ 是使用 Erlang 语言开发的开源消息队列系统,基于 AMQP 协议来实现。
AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。
AMQP协议更多用在企业系统内,对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。
2011年初,Linkin开源了 Kafka 这个优秀的消息中间件,淘宝中间件团队在对 Kafka 做过充分 Review 之后,Kafka 无限消息堆积,高效的持久化速度吸引了我们,但是同时发现这个消息系统主要定位于日志传输,对于使用在淘宝交易、订单、充值等场景下还有诸多特性不满足。
为此淘宝重新用 Java 语言编写了 RocketMQ,定位于非日志的可靠消息传输(日志场景也OK),目前RocketMQ 在阿里集团被广泛应用在订单,交易,充值,流计算,消息推送,日志流式处理,binglog 分发等场景。
Kafka是 LinkedIn 开源的分布式发布-订阅消息系统,目前归属于 Apache 定级项目。
Kafka 主要特点是基于 Pull 的模式来处理消息消费,追求高吞吐量,一开始的目的就是用于日志收集和传输。
0.8版本开始支持复制,不支持事务,对消息的重复、丢失、错误没有严格要求,适合产生大量数据的互联网服务的数据收集业务。
特性 | RabbitMq | RocketMQ | Kafka |
---|---|---|---|
开发语言 | Erlang | Java | Scala 和 Java |
成熟度 | 成熟 | 比较成熟 | 成熟的日志领域 |
时效性 | 微秒级 | 毫秒级 | 毫秒级 |
社区活跃度 | 高 | 高 | 高 |
单机吞吐量 | 5.9W/S,CPU资源消耗较高;消息持久化场景下在2.6w/s左右 | 11.6w/s,RocketMQ 的消息写入内存后即返回ack,由单独的线程专门做刷盘的操作,所有的消息均是顺序写文件。(内存消耗相对较大) | 17.3w/s,这主要取决于它的队列模式保证了写磁盘的过程是线性IO。此时broker磁盘IO已达瓶颈。(cpu消耗相对较大) |
topic数量对吞吐量的影响 | topic可以达到几百,几千个的级别,吞吐量会有较小幅度的下降这是 RocketMQ的一大优势,在同等机器下,可以支撑大量的topic | topic 从几十个到几百个的时候,吞吐量会大幅度下降所以在同等机器下,kafka 尽量保证 topic 数量不要过多。如果要支撑大规模topic,需要增加更多的机器资源 | |
可用性 | 高,基于主从架构实现高可用性 | 非常高,分布式架构 | 非常高,kafka是分布式的,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用 |
消息可靠性 | 以 broker 为中心,有消息的确认机制 | 经过参数优化配置,可以做到0丢失 | 经过参数优化配置,消息可以做到0丢失。以 consumer 为中心,无消息的确认机制 |
功能支持 | 基于erlang开发,所以并发能力很强,性能极其好,延时很低 | MQ功能较为完善,还是分布式的,扩展性好 | 功能较为简单,主要支持简单的MQ功能,在大数据领域的实时计算以及日志采集被大规模使用,是事实上的标准 |
实际使用场景对比:
https://baike.baidu.com/item/MQ/9062942?fr=aladdin
https://www.jianshu.com/p/d948b18f5849
https://blog.csdn.net/ThinkWon/article/details/104588612