消息中间件(RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ等)的定义、组成、特点、优缺点、应用场景&面试题

大家都参与过网上电商平台的秒杀活动吧,一般的秒杀活动辄几百万的参与人数,而“双十一”的参与人数更是已“亿”为计量单位。那么这些电商平台的系统架构是怎样的,它们是如何做到承担每秒几万、几十万的并发访问请求的,所有的请求都是直接落到数据库的吗?当然,数据库不可能承担如此高的负载请求,那这些系统架构引入了哪些“大杀器”呢?这篇文章将讲解其中的关键技术之一消息中间件,并在文章中进一步对消息中间件做详细的讲解。

1. 消息队列

1.1什么是消息队列

消息队列(Message queue,简称MQ),是指利用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行分布式系统的集成。从字面理解就是一个保存消息的一个容器。那么我们为何需要这样一个容器呢?其实就是为了解耦各个系统,我们来举个例子:

消息中间件(RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ等)的定义、组成、特点、优缺点、应用场景&面试题_第1张图片

场景:系统A负责生成userID,并调用系统B、C。如果系统BC频繁变化是否需要userID参数,则系统A的代码就得不断变化,如果哪天又来了系统DEF……也需要这个参数,则系统A又要加入很多业务逻辑,这样子各他系统之间就容易产生相互影响,另外大量的系统与A发生交互也容易产生问题。

消息中间件(RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ等)的定义、组成、特点、优缺点、应用场景&面试题_第2张图片

加了消息队列后,A只负责产生userID,至于谁要用这个参数,怎么用?系统A不管。对这个数据感兴趣的系统自己去取用即可,各个系统之间就实现了解耦。而且解耦后,整个服务业变成了一个异步的方式,系统A产生数据后,不用依次调用BCD来累计耗时,各系统可以同时来取用消息队列的数据进行处理,加大吞吐。

1.2常见的消息队列

当前使用较多的消息队列有RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ、MetaMQ等,而部分数据库如Redis、MySQL以及phxsql也可实现消息队列的功能。

2. 消息队列的组成

2.1 Broker

消息服务器,作为server提供消息核心服务。

2.2 Producer

消息生产者,业务的发起方,负责生产消息传输给broker。

2.3 Consumer

消息消费者,业务的处理方,负责从broker获取消息并进行业务逻辑处理。

2.4 Topic

主题,发布订阅模式下的消息统一汇集地,不同生产者向topic发送消息,由MQ服务器分发到不同的订阅者,实现消息的广播。

2.5 Queue

队列,PTP模式下,特定生产者向特定queue发送消息,消费者订阅特定的queue完成指定消息的接收。

2.6 Message

消息体,根据不同通信协议定义的固定格式进行编码的数据包,来封装业务数据,实现消息的传输。

3. 常见消息队列介绍

3.1 RocketMQ

消息中间件(RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ等)的定义、组成、特点、优缺点、应用场景&面试题_第3张图片

阿里系下开源的一款分布式、队列模型的消息中间件,原名Metaq,3.0版本名称改为RocketMQ,是阿里参照kafka设计思想使用java实现的一套mq,并做出了自己的一些改进,消息可靠性上比Kafka更好。同时将阿里系内部多款mq产品(Notify、metaq)进行整合,只维护核心功能,去除了所有其他运行时依赖,保证核心功能最简化,在此基础上配合阿里上述其他开源产品实现不同场景下mq的架构,RocketMQ在阿里内部被广泛应用在订单、交易、充值、流计算、消息推送、日志流式处理、binglog分发等场景。

主要特性

1. 基于队列模型:具有高性能、高可靠、高实时、分布式等特点;

2. Producer、Consumer、队列都支持分布式;

3. Producer向一些队列轮流发送消息,队列集合称为Topic。Consumer如果做广播消费,则一个Consumer实例消费这个Topic对应的所有队列;如果做集群消费,则多个Consumer 实例平均消费这个Topic对应的队列集合;

4. 能够保证严格的消息顺序;

5. 提供丰富的消息拉取模式;

6. 高效的订阅者水平扩展能力;

7. 实时的消息订阅机制;

8. 亿级消息堆积 能力;

9. 较少的外部依赖;

10. 提供针对消息的过滤功能。

阿里官方提供了一些不同于kafka的对比差异:

https://rocketmq.apache.org/docs/motivation/

优点

1. 单机支持1万以上持久化队列;

2. RocketMQ的所有消息都是持久化的,先写入系统PAGECACHE,然后刷盘,可以保证内存与磁盘都有一份数据,而访问时,直接从内存读取。

3. 模型简单,接口易用(JMS的接口很多场合并不太实用);

4. 性能非常好,可以允许大量堆积消息在Broker中;

5. 支持多种消费模式,包括集群消费、广播消费等;

6. 各个环节分布式扩展设计,支持主从和高可用;

7. 开发度较活跃,版本更新很快。

缺点

1. 支持的客户端语言不多,目前是Java及C++,其中C++还不成熟;

2. RocketMQ社区关注度及成熟度也不及RabbitMQ、Kafka;

3. 没有Web管理界面,提供了一个 CLI (命令行界面) 管理工具带来查询、管理和诊断各种问题;

4. 没有在MQ核心里实现JMS等接口;

3.2 RabbitMQ

消息中间件(RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ等)的定义、组成、特点、优缺点、应用场景&面试题_第4张图片

RabbitMQ于2007年发布,是一个在AMQP(高级消息队列协议)基础上完成的,可复用的企业消息系统,是当前最主流的消息中间件之一。本身支持很多的协议:AMQP,XMPP, SMTP,STOMP,也正是如此,使的它变的非常重量级,更适合于企业级的开发。同时实现了Broker架构,核心思想是生产者不会将消息直接发送给队列,消息在发送给客户端时先在中心队列排队。对路由(Routing),负载均衡(Load balance)、数据持久化都有很好的支持。多用于进行企业级的ESB整合。

RabbitMQ是使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现。AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。AMQP协议更多用在企业系统内,对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。

主要特性

1. 可靠性:提供了多种技术可以让你在性能和可靠性之间进行权衡。这些技术包括持久性机制、投递确认、发布者证实和高可用性机制;

2. 灵活的路由:消息在到达队列前是通过交换机进行路由的。RabbitMQ为典型的路由逻辑提供了多种内置交换机类型。如果你有更复杂的路由需求,可以将这些交换机组合起来使用,你甚至可以实现自己的交换机类型,并且当做RabbitMQ的插件来使用;

3. 消息集群:在相同局域网中的多个RabbitMQ服务器可以聚合在一起,作为一个独立的逻辑代理来使用;

4. 队列高可用:队列可以在集群中的机器上进行镜像,以确保在硬件问题下还保证消息安全;

5. 支持多种协议:支持多种消息队列协议;

6. 支持多种语言:用Erlang语言编写,支持只要是你能想到的所有编程语言;

7. 管理界面:RabbitMQ有一个易用的用户界面,使得用户可以监控和管理消息Broker的许多方面;

8. 跟踪机制:如果消息异常,RabbitMQ 提供消息跟踪机制,使用者可以找出发生了什么;

9. 插件机制:提供了许多插件,来从多方面进行扩展,也可以编写自己的插件。

优点

1. 由于Erlang语言的特性,消息队列性能较好,支持高并发;

2. 健壮、稳定、易用、跨平台、支持多种语言、文档齐全;

3. 有消息确认机制和持久化机制,可靠性高;

4. 高度可定制的路由;

5. 管理界面较丰富,在互联网公司也有较大规模的应用,社区活跃度高。

缺点

1. 尽管结合 Erlang 语言本身的并发优势,性能较好,但是不利于做二次开发和维护;

2. 实现了代理架构,意味着消息在发送到客户端之前可以在中央节点上排队。此特性使得RabbitMQ易于使用和部署,但是使得其运行速度较慢,因为中央节点 增加了延迟,消息封装后也比较大;需要学习比较复杂的接口和协议,学习和维护成本较高。

3.3 ActiveMQ

消息中间件(RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ等)的定义、组成、特点、优缺点、应用场景&面试题_第5张图片

Apache下的一个子项目。使用Java完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现,少量代码就可以高效地实现高级应用场景。可插拔的传输协议支持,比如:in-VM, TCP, SSL, NIO, UDP, multicast, JGroups and JXTA transports。RabbitMQ、ZeroMQ、ActiveMQ均支持常用的多种语言客户端 C++、Java、.Net,、Python、 Php、 Ruby等。

它非常快速,支持多种语言的客户端和协议,而且可以非常容易的嵌入到企业的应用环境中,并有许多高级功能。

主要特性

1. 服从JMS规范:JMS 规范提供了良好的标准和保证,包括:同步 或 异步 的消息分发,一次和仅一次的消息分发,消息接收和订阅等等。遵从JMS规范的好处在于,不论使用什么JMS实现提供者,这些基础特性都是可用的;

2. 连接灵活性:ActiveMQ提供了广泛的连接协议,支持的协议有:HTTP/S,IP多播,SSL,TCP,UDP等等。对众多协议的支持让ActiveMQ拥有了很好的灵活性;

3. 支持的协议种类多:OpenWire、STOMP、REST、XMPP、AMQP;

4. 持久化插件和安全插件:ActiveMQ提供了多种持久化选择。而且,ActiveMQ的安全性也可以完全依据用户需求进行自定义鉴权和授权;

5. 支持的客户端语言种类多:除了Java之外,还有:C/C++,.NET,Perl,PHP,Python,Ruby;

6. 代理集群:多个ActiveMQ代理可以组成一个集群来提供服务;

7. 异常简单的管理:ActiveMQ是以开发者思维被设计的。所以,它并不需要专门的管理员,因为它提供了简单又使用的管理特性。有很多中方法可以监控ActiveMQ不同层面的数据,包括使用在JConsole或者在ActiveMQ的WebConsole中使用JMX。通过处理JMX的告警消息,通过使用命令行脚本,甚至可以通过监控各种类型的日志。

优点

1. 跨平台(JAVA编写与平台无关,ActiveMQ几乎可以运行在任何的JVM上);

2. 可以用JDBC:可以将数据持久化到数据库。虽然使用JDBC会降低ActiveMQ的性能,但是数据库一直都是开发人员最熟悉的存储介质;

3. 支持JMS规范:支持JMS规范提供的统一接口;

4. 支持自动重连和错误重试机制;

5. 有安全机制:支持基于shiro,jaas等多种安全配置机制,可以对Queue/Topic进行认证和授权;

6. 监控完善:拥有完善的监控,包括WebConsole,JMX,Shell命令行,Jolokia的RESTful API;

7. 界面友善:提供的WebConsole可以满足大部分情况,还有很多第三方的组件可以使用,比如hawtio;

缺点

1. 社区活跃度不及RabbitMQ高;

2. 根据其他用户反馈,会出莫名其妙的问题,会丢失消息;

3. 目前重心放到activemq6.0产品Apollo,对5.x的维护较少;

4. 不适合用于上千个队列的应用场景;

3.4 Kafka

消息中间件(RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ等)的定义、组成、特点、优缺点、应用场景&面试题_第6张图片

Apache下的一个子项目,使用scala实现的一个高性能分布式Publish/Subscribe消息队列系统,Kafka是一个开源的分布式发布-订阅消息系统。它最初由LinkedIn公司基于独特的设计实现为一个分布式的日志提交系统(a distributed commit log),之后成为Apache项目的一部分。Kafka性能高效、可扩展良好并且可持久化。它的分区特性,可复制和可容错都是其不错的特性。

Kafka主要为高吞吐量的订阅发布系统而设计,追求速度与持久化。kafka中的消息由键、值、时间戳组成,kafka不记录每个消息被谁使用,只通过偏移量记录哪些消息是未读的,kafka中可以指定消费组来实现订阅发布的功能。

主要特性

1. 快速持久化:通过磁盘顺序读写与零拷贝机制,可以在O(1)的系统开销下进行消息持久化;

2. 高吞吐:在一台普通的服务器上既可以达到10W/s的吞吐速率;

3. 完全的分布式系统:Broker、Producer和Consumer都原生自动支持分布式,依赖zookeeper自动实现复杂均衡;

4. 高堆积:支持topic下消费者较长时间离线,消息堆积量大;

5. 支持Hadoop数据并行加载:对于像Hadoop的一样的日志数据和离线分析系统,但又要求实时处理的限制,这是一个可行的解决方案;

6. 支持同步和异步复制两种高可用机制;

7. 支持数据批量发送和拉取;

8. 零拷贝技术(zero-copy):减少IO操作步骤,提高系统吞吐量;

9. 数据迁移、扩容对用户透明;

10. 无需停机即可扩展机器;

11. 其他特性:丰富的消息拉取模型、高效订阅者水平扩展、实时的消息订阅、亿级的消息堆积能力、定期删除机制;

优点

1. 客户端语言丰富:支持Java、.Net、PHP、Ruby、Python、Go等多种语言;

2. 高性能:单机写入TPS约在100万条/秒,消息大小10个字节;

3. 提供完全分布式架构,并有replica机制,拥有较高的可用性和可靠性,理论上支持消息无限堆积;

4. 支持批量操作;

5. 消费者采用Pull方式获取消息。消息有序,通过控制能够保证所有消息被消费且仅被消费一次;

6. 有优秀的第三方KafkaWeb管理界面Kafka-Manager;

7. 在日志领域比较成熟,被多家公司和多个开源项目使用。

缺点

1. Kafka单机超过64个队列/分区时,Load时会发生明显的飙高现象。队列越多,负载越高,发送消息响应时间变长;

2. 使用短轮询方式,实时性取决于轮询间隔时间;

3. 消费失败不支持重试;

4. 支持消息顺序,但是一台代理宕机后,就会产生消息乱序;

5. 社区更新较慢。

3.5 Redis

使用C语言开发的一个Key-Value的NoSQL数据库,开发维护很活跃,虽然它是一个Key-Value数据库存储系统,但它本身支持MQ功能,所以完全可以当做一个轻量级的队列服务来使用。对于RabbitMQ和Redis的入队和出队操作,各执行100万次,每10万次记录一次执行时间。测试数据分为128Bytes、512Bytes、1K和10K四个不同大小的数据。实验表明:入队时,当数据比较小时Redis的性能要高于RabbitMQ,而如果数据大小超过了10K,Redis则慢的无法忍受;出队时,无论数据大小,Redis都表现出非常好的性能,而RabbitMQ的出队性能则远低于Redis。

3.6 ZeroMQ

号称最快的消息队列系统,专门为高吞吐量/低延迟的场景开发,在金融界的应用中经常使用,偏重于实时数据通信场景。ZMQ能够实现RabbitMQ不擅长的高级/复杂的队列,但是开发人员需要自己组合多种技术框架,开发成本高。因此ZeroMQ具有一个独特的非中间件的模式,更像一个socket library,你不需要安装和运行一个消息服务器或中间件,因为你的应用程序本身就是使用ZeroMQ API完成逻辑服务的角色。但是ZeroMQ仅提供非持久性的队列,如果down机,数据将会丢失。如:Twitter的Storm中使用ZeroMQ作为数据流的传输。

ZeroMQ套接字是与传输层无关的:ZeroMQ套接字对所有传输层协议定义了统一的API接口。默认支持 进程内(inproc) ,进程间(IPC) ,多播,TCP协议,在不同的协议之间切换只要简单的改变连接字符串的前缀。可以在任何时候以最小的代价从进程间的本地通信切换到分布式下的TCP通信。ZeroMQ在背后处理连接建立,断开和重连逻辑。

主要特性

1. 无锁的队列模型:对于跨线程间的交互(用户端和session)之间的数据交换通道pipe,采用无锁的队列算法CAS;在pipe的两端注册有异步事件,在读或者写消息到pipe的时,会自动触发读写事件。

2. 批量处理的算法:对于批量的消息,进行了适应性的优化,可以批量的接收和发送消息。

3. 多核下的线程绑定,无须CPU切换:区别于传统的多线程并发模式,信号量或者临界区,zeroMQ充分利用多核的优势,每个核绑定运行一个工作者线程,避免多线程之间的CPU切换开销。

3.7 概述适用场景

从公司基础建设力量角度

1.中小型软件公司,建议选RabbitMQ,一方面,erlang语言天生具备高并发的特性,而且他的管理界面用起来十分方便。他的弊端也在这里,虽然RabbitMQ是开源的,然而国内有几个能定制化开发erlang的程序员呢?所幸,RabbitMQ的社区十分活跃,可以解决开发过程中遇到的bug,这点对于中小型公司来说十分重要。不考虑RocketMQ和kafka的原因是,一方面中小型软件公司不如互联网公司,数据量没那么大,选消息中间件,应首选功能比较完备的,所以kafka排除。不考虑RocketMQ的原因是,RocketMQ是阿里出品,如果阿里放弃维护RocketMQ,中小型公司一般抽不出人来进行RocketMQ的定制化开发,因此不推荐。

2.大型软件公司,根据具体使用在RocketMQ和kafka之间二选一。一方面,大型软件公司,具备足够的资金搭建分布式环境,也具备足够大的数据量。针对RocketMQ,大型软件公司也可以抽出人手对RocketMQ进行定制化开发,毕竟国内有能力改JAVA源码的人,还是相当多的。至于kafka,根据业务场景选择,如果有日志采集功能,肯定是首选kafka了。

从业务场景角度出发

1.RocketMQ定位于非日志的可靠消息传输(日志场景也OK),目前RocketMQ在阿里集团被广泛应用在订单,交易,充值,流计算,消息推送,日志流式处理,binglog分发等场景。

2.Kafka是LinkedIn开源的分布式发布-订阅消息系统,目前归属于Apache定级项目。Kafka主要特点是基于Pull的模式来处理消息消费,追求高吞吐量,一开始的目的就是用于日志收集和传输。0.8版本开始支持复制,不支持事务,对消息的重复、丢失、错误没有严格要求,适合产生大量数据的互联网服务的数据收集业务。

3.RabbitMQ是使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现。AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。AMQP协议更多用在企业系统内,对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。

4. 主要消息队列的比较

消息中间件(RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ等)的定义、组成、特点、优缺点、应用场景&面试题_第7张图片

5. 消息队列的特点

1、先进先出:消息队列的顺序在入队的时候就基本已经确定了,一般是不需人工干预的。

2、发布订阅:发布订阅是一种很高效的处理方式,如果不发生阻塞,基本可以当成是同步操作。

3、持久化:持久化确保消息队列的使用不只是一个部分场景的辅助工具,而是让消息队列能像数据库一样存储核心的数据。

4、分布式:在现在大流量、大数据的使用场景下,支持分布式的部署,才能被广泛使用。消息队列的定位就是一个高性能的中间件。

6. 消息队列模式分类

6.1点对点

PTP点对点:使用queue作为通信载体

消息中间件(RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ等)的定义、组成、特点、优缺点、应用场景&面试题_第8张图片

说明:

消息生产者生产消息发送到queue中,然后消息消费者从queue中取出并且消费消息。

消息被消费以后,queue中不再存储,所以消息消费者不可能消费到已经被消费的消息。 Queue支持存在多个消费者,但是对一个消息而言,只会有一个消费者可以消费。

6.2发布/订阅

Pub/Sub发布订阅(广播):使用topic作为通信载体

消息中间件(RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ等)的定义、组成、特点、优缺点、应用场景&面试题_第9张图片

说明:

消息生产者(发布)将消息发布到topic中,同时有多个消息消费者(订阅)消费该消息。和点对点方式不同,发布到topic的消息会被所有订阅者消费。

queue实现了负载均衡,将producer生产的消息发送到消息队列中,由多个消费者消费。但一个消息只能被一个消费者接受,当没有消费者可用时,这个消息会被保存直到有一个可用的消费者。

topic实现了发布和订阅,当你发布一个消息,所有订阅这个topic的服务都能得到这个消息,所以从1到N个订阅者都能得到一个消息的拷贝。

7. 消息中间件的优势

7.1系统解耦

交互系统之间没有直接的调用关系,只是通过消息传输,故系统侵入性不强,耦合度低。

7.2提高系统响应时间

例如原来的一套逻辑,完成支付可能涉及先修改订单状态、计算会员积分、通知物流配送几个逻辑才能完成;通过MQ架构设计,就可将紧急重要(需要立刻响应)的业务放到该调用方法中,响应要求不高的使用消息队列,放到MQ队列中,供消费者处理。

7.3为大数据处理架构提供服务

通过消息作为整合,大数据的背景下,消息队列还与实时处理架构整合,为数据处理提供性能支持。

7.4Java消息服务——JMS

Java消息服务(Java Message Service,JMS)应用程序接口是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。

JMS中的P2P和Pub/Sub消息模式:点对点(point to point, queue)与发布订阅(publish/subscribe,topic)最初是由JMS定义的。这两种模式主要区别或解决的问题就是发送到队列的消息能否重复消费(多订阅)。

8. 消息中间件应用场景

以一个订单系统为例,讲解消息中间件解决了系统中的异步、解耦、削峰问题,订单系统的框架如下所示。

消息中间件(RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ等)的定义、组成、特点、优缺点、应用场景&面试题_第10张图片

8.1 异步

有些业务不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。

对于订单系统,当用户下单并付款商品后,系统需要完成更新订单状态、减少商品库存、给用户下发一些卡券、满减优惠红包、发送短信通知等操作,如果这些操作采用串行化的方式,举个例子,每个操作100ms,那么串行的全部完成这些操作需要500ms,如果在成功付款后,只完成核心操作,非核心的操作采用异步化的方式完成,即只需要完成订单状态更新与库存削减,其它操作采用异步化的方式完成,那么只需要200ms,速度提高一倍多。

因此,消息中间件就是用来实现此异步化的操作的,订单系统通过发送订单支付完成消息给消息中间件集群,消息中间件集群再将消息发送到卡券系统、短信系统等,实现异步化的操作,如图所示。

消息中间件(RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ等)的定义、组成、特点、优缺点、应用场景&面试题_第11张图片

8.2 解耦

降低工程间的强依赖程度,针对异构系统进行适配。在项目启动之初来预测将来项目会碰到什么需求,是极其困难的。通过消息系统在处理过程中间插入了一个隐含的、基于数据的接口层,两边的处理过程都要实现这一接口,当应用发生变化时,可以独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束。

在用户完成订单支付后,订单系统需通知第三方物流仓储系统去完成商品的出库,一般情况下订单系统会调用物流系统的接口,物流系统执行一堆代码逻辑和数据库操作后,将执行接口返回给订单系统,正常情况下,该操作没有什么问题。

但是如果某天物流系统挂了,或是因为某些原因接口运行了几秒才执行完毕,那么订单系统收不到接口返回成功的消息,就无法告知用户订单完成,对于用户来说,是非常差的体验。因此,我们在开发过程中,并不能完全地相信第三方系统,要尽量做到系统间的解耦。

因此,消息中间件被用来实现系统间的解耦,订单系统发送消息到消息中间件集群,消息中间件集群将消息发送到第三方物流系统,订单系统此时并不关心物流系统的执行情况,直接返回订单成功的消息,从而实现系统间的解耦,也避免了订单系统的性能抖动。如图所示。

消息中间件(RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ等)的定义、组成、特点、优缺点、应用场景&面试题_第12张图片

8.3 削峰

用于高并发场景,进行削峰。

流量削峰在秒杀系统中应用非常广泛。如果在秒杀活动中每秒上万的请求全部落到数据库,那么必将会导致数据库挂掉,从而导致订单系统崩溃。引入消息中间件后,将用户的请求写入消息队列,如果消息队列的长度超过最大值,那么直接抛弃用户的请求并返回商品秒杀结束的信息给用户。消息中间件集群中积攒的几万条消息可被订单系统慢慢的消费处理掉。瞬间上万并发的压力由消息中间件来抗,订单系统只需要从消息中间件中慢慢拉取消息进行消费,不会对数据库造成影响。

8.4 冗余

有些情况下,处理数据的过程会失败。除非数据被持久化,否则将造成丢失。消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险。许多消息队列所采用的”插入-获取-删除”范式中,在把一个消息从队列中删除之前,需要你的处理系统明确的指出该消息已经被处理完毕,从而确保你的数据被安全的保存直到你使用完毕。

8.5 扩展性

因为消息队列解耦了你的处理过程,所以增大消息入队和处理的频率是很容易的,只要另外增加处理过程即可。不需要改变代码、不需要调节参数。便于分布式扩容。

8.6 过载保护

在访问量剧增的情况下,应用仍然需要继续发挥作用,但是这样的突发流量无法提取预知;如果以为了能处理这类瞬间峰值访问为标准来投入资源随时待命无疑是巨大的浪费。使用消息队列能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷的请求而完全崩溃。

8.7 可恢复性

系统的一部分组件失效时,不会影响到整个系统。消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。

8.8 顺序保证

在大多使用场景下,数据处理的顺序都很重要。大部分消息队列本来就是排序的,并且能保证数据会按照特定的顺序来处理。

8.9 缓冲

在任何重要的系统中,都会有需要不同的处理时间的元素。消息队列通过一个缓冲层来帮助任务最高效率的执行,该缓冲有助于控制和优化数据流经过系统的速度。以调节系统响应时间。

8.10 数据流处理

分布式系统产生的海量数据流,如:业务日志、监控数据、用户行为等,针对这些数据流进行实时或批量采集汇总,然后进行大数据分析是当前互联网的必备技术,通过消息队列完成此类数据收集是最好的选择。

9. 消息中间件常用协议

9.1 AMQP协议

AMQP即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同开发语言等条件的限制。

优点:可靠、通用

9.2 MQTT协议

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,有可能成为物联网的重要组成部分。该协议支持所有平台,几乎可以把所有联网物品和外部连接起来,被用来当做传感器和致动器(比如通过Twitter让房屋联网)的通信协议。

优点:格式简洁、占用带宽小、移动端通信、PUSH、嵌入式系统

9.3 STOMP协议

STOMP(Streaming Text Orientated Message Protocol)是流文本定向消息协议,是一种为MOM(Message Oriented Middleware,面向消息的中间件)设计的简单文本协议。STOMP提供一个可互操作的连接格式,允许客户端与任意STOMP消息代理(Broker)进行交互。

优点:命令模式(非topic\queue模式)

9.4 XMPP协议

XMPP(可扩展消息处理现场协议,Extensible Messaging and Presence Protocol)是基于可扩展标记语言(XML)的协议,多用于即时消息(IM)以及在线现场探测。适用于服务器之间的准即时操作。核心是基于XML流传输,这个协议可能最终允许因特网用户向因特网上的其他任何人发送即时消息,即使其操作系统和浏览器不同。

优点:通用公开、兼容性强、可扩展、安全性高,但XML编码格式占用带宽大

9.5 其他基于TCP/IP自定义的协议

有些特殊框架(如:redis、kafka、zeroMq等)根据自身需要未严格遵循MQ规范,而是基于TCP\IP自行封装了一套协议,通过网络socket接口进行传输,实现了MQ的功能。

10. 消息中间件各种面试题

以下内容链接摘自:

作者:jsbintask

链接:https://www.jianshu.com/p/4491cba335d1

消息中间件面试题:消息丢失怎么办?

消息中间件面试题:消息队列的优缺点,区别

消息中间件面试题:消息中间件的高可用

消息中间件面试题:如何保证消息的顺序性

消息中间件面试题:如何保证消息不被重复消费

消息中间件面试题:如何解决消息队列的延时以及过期失效问题?消息队列满了以后该怎么处理?有几百万消息持续积压几小时呢?

消息中间件面试题:如果让你写一个消息队列,该如何进行架构设计?

你可能感兴趣的