咱们知道,目前市面上的MQ包括Kafka、RabbitMQ、ZeroMQ、RocketMQ等等。面试
那么他们之间究竟有什么本质区别,分别适用于什么场景呢?服务器
上述抛出的问题,一样在很多公司的Java工程师面试中出现,特别是当你简历上的技术栈包含了这些技术,面试官每每喜欢用这个问题,对你进行摸底考察。网络
本文咱们就一块儿来探讨一下。架构
(1)有Broker的暴力路由异步
这个流派最典型的就是Kafka,Kafka实际上为了提高性能,简化了MQ功能模型,仅仅提供了一些最基础的MQ相关的功能,可是大幅度优化和提高了吞吐量。分布式
首先,这个流派必定是有一个Broker角色的,也就是说,Kafka须要部署一套服务器集群,每台机器上都有一个Kafka Broker进程,这个进程就负责接收请求,存储数据,发送数据。性能
Kafka的生产消费模型作的相对是比较暴力简单的,就是简单的数据流模型。大数据
简单来讲,他有一个概念,叫作“Topic”,你能够往这个“Topic”里写数据,而后让别人从这里来消费。优化
这个Topic能够划分为多个Partition,每一个Partition放一台机器上,存储一部分数据。架构设计
在写消息到Topic的时候,会自动把你这个消息给分发到某一个Partition上去。
而后消费消息的时候,有一个Consumer Group的概念,你部署在多台机器上的Consumer能够组成一个Group,一个Partition只能给一个Consumer消费,一个Cosumer能够消费多个Partition,这是最最核心的一点。
经过这个模型,保证一个Topic里的每条消息,只会交给Consumer Group里的一个Consumer来消费,造成了一个Queue(队列)的效果。
假如你想要有一个Queue的效果,也就是但愿不停的往Queue里写数据,而后多个消费者消费,每条消息就只能给一个消费者,那么经过Kafka来实现,其实就是生产者写多个Partition,每一个Partition只能给Consumer Group中的一个Consumer来消费。以下图所示:
若是要实现Publish/Subscribe的模型呢?就是说生产者发送的每条消息,都要让全部消费都消费到,怎么实现?
那就让每一个消费者都是一个独立的消费组,这样每条消息都会发送给全部的消费组,每一个消费组里那惟一的一个消费者必定会消费到全部的消息。
可是除此以外,Kafka就没有任何其余的消费功能了,就是如此简单,因此属于一种比较暴力直接的流派。
它就是简单的消费模型,实现最基础的Queue和Pub/Sub两种消费模型,可是内核中大幅度优化和提高了性能以及吞吐量。
因此Kafka天生适合的场景,就是大数据领域的实时数据计算的场景。
由于在大数据的场景下,一般是弱业务的场景,没有太多复杂的业务系统交互,而主要是大量的数据流入Kafka,而后进行实时计算。
因此就是须要简单的消费模型,可是必须在内核中对吞吐量和性能进行大幅度的优化。
所以Kafka技术一般是在大数据的实时数据计算领域中使用的,好比说每秒处理几十万条消息,甚至每秒处理上百万条消息。
(2)有Broker的复杂路由
第二个流派,就是RabbitMQ为表明的流派,他强调的不是说如何提高性能和吞吐量,关注的是说要提供很是强大、复杂并且完善的消息路由功能。
因此对于RabbitMQ而言,他就不是那么简单的Topic-Partition的消费模型了。
在RabbitMQ中引入了一个很是核心的概念,叫作Exchange,这个Exchange就是负责根据复杂的业务规则把消息路由到内部的不一样的Queue里去。
举个例子,若是要实现最简单的队列功能,就是让exchange往一个queue里写数据,而后多个消费者来消费这个queue里的数据,每条消息只能给一个消费者,那么能够是相似下面的方式。
若是想要实现Pub/Sub的模型,就是一条消息要被全部的消费者给消费到,那么就可让每一个消费者都有一个本身的Queue,而后绑定到一个Exchange上去。
接着,这个Exchange就设定把消息路由给全部的Queue便可,以下面这样。
此时Exchange能够把每条消息都路由给全部的Queue,每一个Consumer均可以从本身的Queue里拿到全部的消息。
RabbitMQ这种流派,其实最核心的是,基于Exchange这个概念,他能够作不少复杂的事情。
好比:若是你想要某个Consumer只能消费到某一类数据,那么Exchange能够把消息里好比带“XXX”前缀的消息路由给某个Queue。或者你能够限定某个Consumer就只能消费某一部分数据。总之在这里你能够作不少的限制,设置复杂的路由规则。
可是也正是由于引入了这种复杂的消费模型,支持复杂的路由功能,致使RabbitMQ在内核以及架构设计上无法像Kafka作的那么的轻量级、高性能、可扩展、高吞吐,因此RabbitMQ在吞吐量上要比Kafka低一个数量级。
因此这种流派的MQ,每每适合用在Java业务系统中,不一样的业务系统须要进行复杂的消息路由。
好比说业务系统A发送了10条消息,其中3条消息是给业务系统B的,7条消息是给业务系统C的,要实现这种复杂的路由模型,就必须依靠RabbitMQ来实现。
固然,对于这种业务系统之间的消息流转而言,可能不须要那么高的吞吐量,可能每秒业务系统之间也就转发几十条或者几百条消息,那么就彻底适合采用RabbitMQ来实现。
(3)无Broker的通讯流派
ZeroMQ表明的是第三种MQ。说白了,他是不须要在服务器上部署的,就是一个客户端的库而已。
也就是说,他主要是封装了底层的Socket网络通信,而后一个系统要发送一条消息给另一个消息消费 。
经过ZeroMQ,本质就是底层ZeroMQ发送一条消息到另一个系统上去。
因此ZeroMQ是去中心化的,不须要跟Kafka、RabbitMQ同样在服务器上部署的。
他主要是用来进行业务系统之间的网络通讯的,有点相似于好比你是一个分布式系统架构,那么此时分布式架构中的各个子系统互相之间要通讯,你是基于Dubbo RPC?仍是Spring Cloud HTTP?
可能上述两种你都不想要,就是要基于原始的Socket进行网络通讯,简单的收发消息而已。
此时就可使用ZeroMQ做为分布式系统之间的消息通讯,以下面那样。
(4)总结
其实如今基本上MQ主要就是这三个流派,不少小众的MQ通常不多有人会用。
并且用MQ的场景主要就是两大类:
因此通常业务系统之间通讯就是会采用RabbitMQ/RocketMQ,须要复杂的消息路由功能的支撑。
大数据的实时计算场景会采用Kafka,须要简单的消费模型,可是超高的吞吐量。
至于ZeroMQ,通常来讲,少数分布式系统中子系统之间的分布式通讯时会采用,做为轻量级的异步化的通讯组件。