MQ技术选型

一、MQ相关知识介绍

1、概述

MQ(Message Queue),即消息队列。早已成为企业IT系统内部通信的核心手段。它具有低耦合、可靠投递、广播、流量控制、最终一致性等一系列功能,成为异步RPC的主要手段之一。当今市面上有很多主流的MQ,如老牌的ActiveMQ、RabbitMQ,炙手可热的Kafka,阿里巴巴自主开发RocketMQ等。

2、MQ模式分类

消息队列包括两种模式:点对点模式 和 发布/订阅模式。

2.1 点对点

PTP点对点:使用queue作为通信载体,如图:
在这里插入图片描述
点对点模式特点说明:
1.消息生产者(Producer)生产消息发送到Queue中,然后消息消费者(Consumer)从Queue中取出并且消费消息。
2.Queue支持存在多个消费者,但对某一个具体的消息而言,只会有一个消费者可以消费。消息一旦被消费后,Queue中不再存储,所以消息消费者不可能消费到已经被消费的消息。
3.Producer与Consumer之间不存在依赖关系,Consumer是否消费某个消息,不影响Producer的下一个消息的生产。
4.Consumer在成功接收消息之后需向队列应答成功(程序中默认自动应答),以便消息队列删除当前接收的消息。

2.2 发布/订阅

Pub/Sub发布订阅(广播):使用topic作为通信载体 ,如图
在这里插入图片描述
发布/订阅模式说明:
1.消息生产者(Publisher)将消息发布到Topic中,同时有多个消息消费者(Subscriber)消费此消息。和点对点方式不同,发布到topic的消息会被所有订阅者消费。
2.queue实现了负载均衡,将producer生产的消息发送到消息队列中,由多个消费者消费。但一个消息只能被一个消费者接受,当没有消费者可用时,这个消息会被保存直到有一个可用的消费者。
3.Publisher和Subscriber之间有时间上的依赖性。针对某个主题(Topic)的订阅者,它必须创建一个订阅者之后,才能消费发布者的消息。
4.topic实现了发布和订阅,当你发布一个消息,所有订阅这个topic的服务都能得到这个消息,所以从1到N个订阅者都能得到一个消息的拷贝。

3、MQ应用场景和优势

3.1 异步处理

有些业务不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。
例如:用户为了使用某个应用,进行注册,系统需要发送注册邮件和注册短信。
在这里插入图片描述
无论串行处理还是并行处理,总处理时间都很大。那使用消息队列呢?
在这里插入图片描述
若使用消息队列,写入完注册信息后,再将信息写入MQ就能直接返回成功给客户端了,然后注册完成。因为写入MQ的时间很快,基本忽略不计。那么引入MQ之后,整个处理时间就只剩下写入注册信息的时间。用时是串行的1/3,并行的1/2。

3.2 应用解耦

降低工程间的强依赖程度,针对异构系统进行适配。在项目启动之初来预测将来项目会碰到什么需求,是极其困难的。通过消息系统在处理过程中间插入了一个隐含的、基于数据的接口层,两边的处理过程都要实现这一接口,当应用发生变化时,可以独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束。
例如:A 系统每次产生数据时,都要将数据发给 B、C 两个系统(通过接口调用)。这个时候如果需要新增了一个 D 系统,如图:
在这里插入图片描述
但是如果使用 MQ,如图:
在这里插入图片描述
A 系统产生一条数据后,只需要放入 MQ 中,哪个系统需要就去 MQ 里消费。如果新增了一个系统,那么订阅 MQ 的消息即可;同理哪个系统不再需要该数据,那么只要取消订阅即可。这样A 系统就跟其他系统实现解耦了。

3.3 限流削峰

在访问量剧增的情况下,应用服务器仍然需要继续发挥作用。使用消息队列能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷的请求而完全崩溃。
例如,某电商网站开展秒杀活动,一般由于瞬间访问暴增,服务器收到请求过大,可能出现无法处理请求或崩溃的情况。如图:
在这里插入图片描述
在高并发的情况下,数据库面对了巨大的访问压力,不仅响应速度减慢,而且甚至挂掉,导致用户页面直接报错。
如果使用MQ,则如下图:
在这里插入图片描述
这样可以将高并发下的数据先行写入MQ中,待消费者进程异步写入数据库中。超出系统处理能力之外的数据会挤压在MQ中,等高峰期过后,就快速将数据处理完成。起到了削峰的作用。

4、几种MQ的对比

下面我们先看下主流的几种MQ的对比,如下表格:

比较项 ActiveMQ RabbitMQ RocketMQ Kafka
所属社区/公司 Apache Mozilla Public License 阿里巴巴 Apache
成熟度及授权 成熟/开源 成熟/开源 比较成熟/开源 成熟/开源
开发语言 java Erlang java Scala&java
客户端支持语言 Java、C/C++、Python、PHP、Perl、.net等 官方支持Erlang,java,Ruby等,社区产出多种语言API,几乎支持所有常用语言 Java、C++ 官方支持java,开源社区有多语言版本,如PHP,Python,Go,C/C++,Ruby等
协议支持 OpenWire、STOMP、REST、XMPP、AMQP 多协议支持:AMQP,XMPP,SMTP,STOMP 自己定义的一套(社区提供JMS–不成熟) 自有协议,社区封装了HTTP协议支持
HA 基于ZooKeeper + LevelDB的Master-Slave实现方式 master/slave模式,master提供服务,slave仅作备份(冷备) 支持多Master模式,多Master多Slave模式,异步复制模式、同步双写 支持replica机制,leader宕掉后,备份自动顶替,并重新选举leader(基于Zookeeper)
数据可靠性 Master/slave,有较低的概率丢失数据 可以保证数据不丢,有slave用作备份 支持异步实时刷盘,同步刷盘,同步复制,异步复制 数据可靠,且有replica机制,有容错容灾能力
单机吞吐量 万级 万级 十万级,支撑高吞吐 十万级,高吞吐,一般配合大数据类的系统进行实时数据计算、日志采集等场景
消息延迟 毫秒级 微秒级 毫秒级 毫秒级以内
流量控制 基于Credit-Based算法,是内部被动触发的保护机制,作用于生产者层面。 支持client和user级别,通过主动设置可将流控作用于生产者或消费者。
持久化能力 默认内存,正常关闭时将内存中未处理的消息持久化文件,如果使用JDBC策略,则入数据库 内存、文件,支持数据堆积。但堆积反过来影响吞吐量 磁盘文件 磁盘文件。只要磁盘容量够,可以做到无限消息堆积
负载均衡 支持 支持 支持 支持
管理界面 一般 较好 命令行界面 官方只提供命令行版,yahoo开源自己的web管理界面
部署方式及难易 独立/容易 独立/容易 独立/容易 独立/容易
功能支持 MQ领域的功能较为完备 基于Erlang开发,并发能力很强,性能极好,时延很低 MQ功能较为完善,还是分布式的,扩展性好 功能较为简单,主要支持简单的MQ功能,在大数据领域的实时计算以及日志采集方面被大规模使用

综合以上对比后,有如下建议: 通常早期大家都使用ActiveMQ,现在使用的不多,毕竟没有经历过大规模吞吐量场景的验证,并且目前社区也不够活跃,不推荐使用。 而RoceketMQ来自阿里出品,目前有越来越多的公司尝试使用,反映确实不错。但社区活跃度不高,那些对自身公司技术实力信心满满的可以考虑。 而Kafka名声在外,之前在一家国产数据库公司时,当时的总架就讲解、推荐过。但目前来看,大数据领域的实时计算、日志采集等场景,kafka是业内标准,社区活跃度极高。有这方面的需求的,可以优先考虑。 最后对于RabbitMQ,无论从软件成熟度,社区活跃度(最新的release版是2019年12月的),还是基本的吞吐能力,以及低时延,界面管理等方面,对于技术实力一般,技术挑战不是很高的公司,可以考虑。RabbitMQ是个不错的选择。 最后,没有完美的产品,只有合适的软件。技术选型毕竟还是要满足业务需求的,满足功能即可。