消息队列(Message Queue)是一种使用高效可靠的数据传输机制来进行平台无关的数据通讯的技术。消息队列拥有消息传递、消息生产、消息消费、优先级消息等功能,为咱们的分布式系统提供了数据通讯、功能解耦、弹性伸缩、数据冗余、限流削峰、异步消息等丰富能力,是分布式系统的一个重要组件。算法
当前开源的消息队列的组件种类繁多,在Github上搜索Message Queue,就有4K+的资源。如此众多的消息队列的开源项目中,咱们耳熟能详的有 RabbitMQ、Kafka、RocketMQ、ActiveMQ、Pulsar等等,不少公司也根据业务需求,定制了本身的消息队列中间件,好比腾讯的CMQ等。这些消息队列组件各自都有各自的特性与侧重点,适合本身的才是最好的。编程
那么如何选择一款最合适的消息队列组件呢?本文选择了RabbitMQ以及Kafka这两款最为普遍使用的消息中间,来探讨一下如何综合考虑各类因素,好比消费模式、性能、语言支持、社区生态等来选择一款称手的消息队列组件。安全
概述服务器
1、RabbitMQ****并发
RabbitMQ是一个历史比较悠久的消息队列中间件,最先能够追溯到2007年,它是使用Erlang语言开发的一个AMQP(Advanced Message Queue Protocol 高级消息队列协议)实现。AMQP是一个应用层协议的开放标准,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受产品、开发语言等条件的限制。RabbitMQ最初起源于金融系统,它在可靠性、可用性、扩展性、消息持久化、高并发等方面的有着卓越的表现。负载均衡
2、Kafka异步
Kafka最先由LinkedIn公司开发,它是一个使用Scala语言开发的支持多分区,多副本而且基于Zookeeper协调的分布式消息系统。它是一种高吞吐、低延迟、可容错的分布式发布订阅消息系统,凭借其可水平扩展的高吞吐率而被普遍使用。在大数据以及流式数据处理方面,Kafka的周边生态也是其一大优点,愈来愈多的开源分布式处理系统如 Cloudera、Apache Storm、Spark、Flink等都支持与 Kafka 集成。编程语言
对比分布式
1、消费模式高并发
消费模式是指消息队列消费消息是时候的策略,分为两种,一种是Push模式,一种是Pull模式。
Push模式是指消息队列的服务器端收到新的消息时主动将消息推送(Push)到消费端,这种消费模式相好比Pull模式会有更好的实时性,可是当服务器端消息较多时,可能出现消费端来不及消费消息从而压垮消费端的状况,须要必定的策略来避免这种状况的发生。
Pull模式是指消息队列的服务器不主动将消息推送给消费端,而是有消费端主动地去从服务器拉取(Pull)消息,通常都是定时拉取或者定量拉取的方式。Pull模式相比与Push模式实时性会差一些,其优点在于消费端能够根据自身消费消息的能力去拉取消息,不会出现消息消费不过来的状况。
RabbitMQ既支持Push模式同时也支持Pull模式,而Kafka仅支持Pull模式。
2、消息持久化
消息持久化是指将消息队列中的消息保存至磁盘中,以防止在发生异常或者服务器宕机等突发状况时发生数据丢失的状况。消息持久化是保证消息队列消息可靠性的关键技术之一。
RabbitMQ在默认状况下是不开启持久化操做,exchange、queue、message等数据都是存储在内存中的,这意味着若是 RabbitMQ 重启、关闭、宕机时全部的信息都将丢失。咱们能够在使用RabbitMQ的时候显式地将exchange、queue、message 等这些数据对象声明为持久化,这样一来,即使服务器宕机或者故障了,咱们也能够将这些数据从硬盘中进行恢复。不过须要注意的是,若是RabbitMQ将全部的这些对象都进行持久化操做,会严重地影响RabbitMQ的性能,由于同步写入磁盘的速度会比写内存慢不少,所以须要在可靠性与性能之间进行权衡。
相比与RabbitMQ须要显式地指定数据类型的持久化,Kafka在设计之初就是依赖磁盘上的文件系统来进行消息的存储。从传统的观念来说,磁盘的读写速度老是比内存慢不少,可是实际上磁盘读写速度的快慢取决于咱们的使用方式:
“一块SATA RAID-5阵列磁盘的线性写速度能够达到几百M_s,而随机写的速度只能是100多KB_s,线性写的速度是随机写的上千倍”
Kafka的数据存储设计是创建在对磁盘文件进行追加写的基础上实现的,数据读取也是顺序访问,这样的数据存储设计带来了很是大的优点:
1. 读操做不会阻塞写操做与其余操做,而且数据大小不会对性能产生影响;
2. 磁盘的容量相比与内存来讲会大不少,消息队列的容量大,而且能够存储任意时间,不用担忧故障致使数据丢失;
综上所述,RabbitMQ和Kafka均支持消息持久化,可是RabbitMQ须要显式地开启持久化,而且开启持久化可能影响消息队列性能。而Kafka从设计之初便支持消息持久化,而且经过优秀的设计保证了高效的消息读写从而保证了较高的吞吐量。
3、性能
性能是咱们进行技术选型的一个重要的参考维度,对于消息队列来说,咱们最为关注的一个性能指标是其吞吐量。在吞吐量这个性能指标上,Kafka基于其优秀的存储以及读写设计,相比于RabbitMQ拥有更高的性能。通常来讲RabbitMQ的单机QPS在万这个级别左右,而Kafka的单机QPS能够达到十万级甚至百万级。
这里我没有进行单机的吞吐量性能测试,援引网上的其余团队进行的一次消息队列单机吞吐量性能测试,让你们感觉一下RabbitMQ与Kafka在吞吐量性能上的差距到底有多少。此次测试对比的是服务端发送小消息(124Byte)的性能,测试的策略是不断增长发送端的压力,直到系统的吞吐量再也不上升,而且系统响应时间增加,这时候服务器端可判断已出现性能瓶颈,这时候的吞吐量即为系统的最高吞吐量。
测试的结果以下:
1. Kafka的单机吞吐量为17.3w/s,达到这个吞吐量时其Broker磁盘IO已经达到了瓶颈,Kafka能达到如此之高的单机吞吐量主要仍是得益于其优秀的设计。
2. RabbitMQ的单机吞吐量为5.95w/s,而且CPU资源消耗较高,主要缘由是其支持AMQP协议,实现地很是重量级,在消息的可靠性与吞吐量上作了取舍。
因而可知,在吞吐量这个性能指标上,Kafka相比与RabbitMQ是具备明显的优点的。
说完了吞吐量,让咱们来讨论一下另外一个性能指标:时延。其实在使用消息队列的场景下讨论时延是有些矛盾的,由于使用消息队列就表明了能够容许较高的时延,由于使用消息队列就可能产生消息的堆积,而且消息堆积的越多,从消息生产到消息消费的时延就越高,在对时延要求比较高的场景下使用消息队列是不合适的,咱们应该使用时延更低的解决方案好比RPC远程过程调用。
4、可靠性
消息队列消息的可靠性也是咱们进行技术选型的关键考虑因素之一,尤为涉及到金融、支付、安全等领域,消息的可靠性就显得尤其重要。保证消息可靠性的关键技术之一消息持久化,上文已经讨论过,RabbitMQ以及Kafka均支持,咱们这里不作赘述。这里咱们来讨论一下消息队列可靠性的另外一个方面,消息投递(消费)的三种不一样的保证:
1. 至多一次投递:消息最多会被投递一次,可是可能丢失
2. 至少一次投递:消息至少会被投递一次,可是可能重复消费
3. 精确一次投递:保证只会被投递一次,有且仅有一次
RabbitMQ以及Kafka都支持至多一次投递以及至少一次投递的保证,同时Kafka在0.11.0.0版本以后,经过事务机制支持了精确一次投递的这种保证。
5、可用性
可靠性是保证消息不会丢失或者重复消费,而这里的可用性则是指系统正常运行时间占总运行时间的百分比,高可用性也就对应着低故障率,那么RabbitMQ与Kafka分别有什么机制来保证系统的高可用呢?
RabbitMQ采用镜像集群的策略来保证系统的高可用性,在镜像集群模式下,不管是消息队列仍是消息都会存储在集群中的多个实例上。也就是说,对于集群中的每一个queue来讲,集群中的每一个节点都有这个queue的完整镜像,这样一来,即便某个节点宕机了,也不会影响整个集群的功能。而且即便是某个主节点宕机了,RabbitMQ集群也能够经过选主算法选举新的主节点从而恢复正常服务。
Kafka的高可用性主要源自于其健壮的副本(Replication)策略。其采用的是相似 PacificA 的一致性协议,经过 ISR(In-Sync-Replica)来保证多副本之间的同步,而且支持强一致性语义(经过 acks 实现)。
6、社区生态及语言支持
从长远的角度来说,社区生态是咱们选择解决方案考虑的关键因素之一,一个开源组件,使用的人越多,社区越活跃,则说明别人踩过的坑也就越多,在咱们开发过程当中遇到问题时就更加容易找到解决方案。同时,若是一个开源组件更新迭代很快,那么它就能够迅速修复之前旧版本的问题,同时快速地迭代开发新功能。
在社区生态这方面,整体来讲,Kafka的生态以及周边环境相比于RabbitMQ更加的成熟和丰富,Kafka拥有更多的开源的客户端、负载均衡组件,同时像Kubernetes、Spark等知名的开源项目也对Kafka有较好的支持。这可能也是得益于在大数据处理方面,Kafka的流式数据的概念和大数据处理更为的契合。
相比于Kafka,RabbitMQ的社区规模可能会较小一些,可是毕竟也是一个久经考验的开源消息队列组件,总的来讲咱们在使用过程当中通常也不会遇到社区解决不了的疑难问题。
在语言支持方面,RabbitMQ和Kafka支持的语言都很是的多,Kafka支持大约17种语言,RabbitMQ支持大约22中语言,主流的变成语言如Java、PHP、C++等等二者均支持,相信在使用的编程语言方面不会有太大的问题。
结语
本文就两种主流的消息队列组件RabbitMQ和Kafka进行了对比和探讨,但愿给你们在消息队列技术选型方面提供必定的思路。你们在选择的时候要注意结合本身的业务需求,团队的技术栈体系选择最为合适的消息队列组件!
本文由博客一文多发平台 OpenWrite 发布!