1.概述
①ActiveMQ是Apache出品的、采用Java语言编写的完全基于JMS1.1规范的面向消息的中间件,为应用程序提供高效的、可扩展的、稳定的和安全的企业级消息通信。不过由于历史原因包袱太重,目前市场份额没有后面三种消息中间件多,其最新架构被命名为Apollo,号称下一代ActiveMQ,有兴趣的同学可行了解。
②RabbitMQ是采用Erlang语言实现的AMQP协议的消息中间件,最初起源于金融系统,用于在分布式系统中存储转发消息。RabbitMQ发展到今天,被越来越多的人认可,这和它在可靠性、可用性、扩展性、功能丰富等方面的卓越表现是分不开的。
③Kafka起初是由LinkedIn公司采用Scala语言开发的一个分布式、多分区、多副本且基于zookeeper协调的分布式消息系统,现已捐献给Apache基金会。它是一种高吞吐量的分布式发布订阅消息系统,以可水平扩展和高吞吐率而被广泛使用。目前越来越多的开源分布式处理系统如Cloudera、Apache Storm、Spark、Flink等都支持与Kafka集成。
④RocketMQ是阿里开源的消息中间件,目前已经捐献个Apache基金会,它是由Java语言开发的,具备高吞吐量、高可用性、适合大规模分布式系统应用等特点,经历过双11的洗礼,实力不容小觑。
⑤ZeroMQ号称史上最快的消息队列,基于C语言开发。ZeroMQ是一个消息处理队列库,可在多线程、多内核和主机之间弹性伸缩,虽然大多数时候我们习惯将其归入消息队列家族之中,但是其和前面的几款有着本质的区别,ZeroMQ本身就不是一个消息队列服务器,更像是一组底层网络通讯库,对原有的Socket API上加上一层封装而已。
⑥腾讯系的PhxQueue、CMQ、CKafka,又比如基于Go语言的NSQ,有时人们也把类似Redis的产品也看做消息中间件的一种
2.RabbitMQ和Kafka的区别
|
类别 |
Kafka |
RabbitMQ |
|
优先级队列(不同于先进先出队列,优先级高的消息具备优先被消费的特权,这样可以为下游提供不同消息级别的保证。前提:消费者的消费速度小于生产者的速度) |
不支持 |
支持,建议优先级大小设置在0-10之间 |
|
延迟队列(举例:三十分钟之内未付款,订单自动取消) |
不支持 |
支持 |
|
死信队列(由于某些原因消息无法被正确的投递,为了确保消息不会被无故的丢弃,一般将其置于一个特殊角色的队列,这个队列一般称之为死信队列。与此对应的还有一个“回退队列”的概念,试想如果消费者在消费时发生了异常,那么就不会对这一次消费进行确认(Ack),进而发生回滚消息的操作之后消息始终会放在队列的顶部,然后不断被处理和回滚,导致队列陷入死循环。为了解决这个问题,可以为每个队列设置一个回退队列,它和死信队列都是为异常的处理提供的一种机制保障。实际情况下,回退队列的角色可以由死信队列和重试队列来扮演) |
不支持 |
支持 |
|
重试队列(可以看成是一种回退队列,具体指消费端消费消息失败时,为防止消息无故丢失而重新将消息回滚到Broker中。与回退队列不同的是重试队列一般分成多个重试等级,每个重试等级一般也会设置重新投递延时,重试次数越多投递延时就越大) |
不支持 |
不支持 |
|
消费模式(分为推(push)模式和拉(pull)模式。推模式是指由Broker主动推送消息至消费端,实时性较好,不过需要一定的流制机制来确保服务端推送过来的消息不会压垮消费端。而拉模式是指消费端主动向Broker端请求拉取(一般是定时或者定量)消息,实时性较推模式差,但是可以根据自身的处理能力而控制拉取的消息量) |
拉模式 |
推模式+拉模式 |
|
广播消费 |
典型的发布订阅模式,能以点对点的形式消费,可以把其消费组的概念看成是队列的概念(支持) |
典型的点对点模式,可以通过设置交换器类型来实现发布订阅模式而达到广播消费的效果(支持,但力度较Kafka弱) |
|
消息回溯(指消息在消费完成之后,还能消费到之前被消费掉的消息) |
支持,Kafka支持按照offset和timestamp两种维度进行消息回溯 |
不支持,RabbitMQ中消息一旦被确认消费就会被标记删除 |
|
消息堆积+持久化(消息堆积分内存式堆积和磁盘式堆积) |
典型的磁盘式堆积(使用顺序存储,避免了随机存储的瓶颈) |
典型的内存式堆积,如果考虑到吞吐这因素,Kafka的堆积效率比RabbitMQ总体上要高很多 |
|
消息追踪 |
不支持,消息追踪可以通过外部系统来支持,但是支持粒度没有内置的细腻 |
支持 |
|
消息过滤(按照既定的过滤规则为下游用户提供指定类别的消息) |
客户端级别的支持 |
不支持,但是二次封装一下也非常简单。 |
|
多租户(实现多用户的环境下公用相同的系统或程序组件,并且仍可以确保各用户间数据的隔离性) |
不支持 |
支持 |
|
多协议支持(有AMQP、MQTT、STOMP、XMPP等) |
只支持定义协议,目前几个主流版本间存在兼容性问题 |
RabbitMQ本身就是AMQP协议的实现,同时支持MQTT、STOMP等协议。 |
|
跨语言支持 |
采用Scala和Java编写,支持多种语言的客户端 |
采用Erlang编写,支持多种语言的客户端 |
|
流量控制 |
支持client和user级别,通过主动设置可将流控作用于生产者或消费者 |
RabbitMQ的流控基于Credit-Based算法,是内部被动触发的保护机制,作用于生产者层面 |
|
消息顺序性 |
支持单分区(partition)级别的顺序性 |
顺序性的条件比较苛刻,需要单线程发送、单线程消费并且不采用延迟队列、优先级队列等一些高级功能,从某种意义上来说不算支持顺序性 |
|
安全机制 |
身份认证和权限控制(TLS/SSL、SASL) |
身份认证和权限控制(TLS/SSL、SASL) |
|
消息幂等性(对于确保消息在生产者和消费者之间进行传输而言一般有三种传输保障(delivery guarantee):At most once,至多一次,消息可能丢失,但绝不会重复传输;At least once,至少一次,消息绝不会丢,但是可能会重复;Exactly once,精确一次,每条消息肯定会被传输一次且仅一次。对于大多数消息中间件而言,一般只提供At most once和At least once两种传输保障,对于第三种一般很难做到,由此消息幂等性也很难保证) |
支持单个生产者单分区单会话的幂等性 |
不支持 |
|
事务性消息 |
支持 |
支持 |
3.性能
消息中间件的性能一般是指其吞吐量,虽然从功能维度上来说,RabbitMQ的优势要大于Kafka,但是Kafka的吞吐量要比RabbitMQ高出1至2个数量级,一般RabbitMQ的单机QPS在万级别之内,而Kafka的单机QPS可以维持在十万级别,甚至可以达到百万级。
时延作为性能维度的一个重要指标,却往往在消息中间件领域所被忽视,因为一般使用消息中间件的场景对时效性的要求并不是很高,如果要求时效性完全可以采用RPC的方式实现。
4.可靠性+可用性
目前而言,在金融支付领域使用RabbitMQ居多,而在日志处理、大数据等方面Kafka使用居多。对于Kafka而言,其采用的是类似PacificA的一致性协议,通过ISR(In-Sync-Replica)来保证多副本之间的同步,并且支持强一致性语义(通过acks实现)。对应的RabbitMQ是通过镜像环形队列实现多副本及强一致性语义的。
扩展能力能够增强其用可用能力及范围,比如前面提到的RabbitMQ支持多种消息协议,这个就是基于其插件化的扩展实现。还有从集群部署上来讲,归功于Kafka的水平扩展能力,其基本上可以达到线性容量提升的水平,在LinkedIn实践介绍中就提及了有部署超过千台设备的Kafka集群。
5.运维管理
对于RabbitMQ而言,最正统的监控管理工具莫过于rabbitmq_management插件,社区内还有AppDynamics, Collectd, DataDog, Ganglia, Munin, Nagios, New Relic, Prometheus, Zenoss等多种优秀的产品
Kafka在此方面也毫不逊色,比如:Kafka Manager, Kafka Monitor, Kafka Offset Monitor, Burrow, Chaperone, Confluent Control Center等产品,尤其是Cruise还可以提供自动化运维的功能
6.比较