Kafka、rabbitmq、zeromq、rocketmq、activemq综合对比(二)

 

Kafka、rabbitmq、zeromq、rocketmq、activemq综合对比(一)

总结

为了尽可能的有参考价值,只关心在生产环境中的重要特性。

Kafka/Jafka

【优势】

Kafka的优势是在超大规模数据的应用场景下体现的。

1>吞吐量极大。

a)充分利用缓冲区,发送端按批次批量发送消息,消费端按批次批量处理消息。

b)高效持久化。

c)批量刷盘。从页面缓存批量刷到磁盘。

2>动态扩展性。

支持热扩展,添加consumer、broker、producer无需关闭服务。

3>高可用、容错性、伸缩性。

4>支持同步到数据库,能与hadoop、hbase等建立数据管道。

基于磁盘的数据存储,通过建立数据管道,可以会把磁盘的消息数据同步到mysql或者hbase等数据库。

消费者可以在进行应用程序维护时离线一段时间,无需担心消息丢失或者堵塞在生产者端。

5>完全的分布式系统,Broker、Producer、Consumer都原生自动支持分布式,自动支持负载均衡,zookeeper负责管理集群成员,搭建、部署、维护分布式集群更加简单。

每一个topic有多个分区,每一个分区有多个副本,当分区首领所在的主机发生问题的时候,kafka会自动从分区副本中选举下一个分区首领,让该分区首领的主机提供服务,分区副本的个数只需要简单配置即可,分区副本的创建和分配,不用我们去操心,负责选举的主机也是kafka选举出来的,选举哪一台主机作为控制器的过程也不用我们操心。

6>流式处理能力。

流数据是数量无限的,连续的,时序性的数据,比如游戏里物体的移动、股票交易、制造商传感器发出的事件、用户行为事件、流经交换机的网络事件等等,公司里的系统一般都包含了大量有价值的数据流。

流式处理不要求实时性达到亚毫秒级的响应,也接受不了要等到第二天才知道结果,基于批处理和实时处理之间。

kafka很多基于Kafka构建的流式处理系统都将kafka作为唯一可靠的数据来源。

a)kafka支持两个基于流的API,一个是底层的Processor API,一个是高级的Stream DSL。

b)kafka0.10.0和更高的版本可以记录时序信息。

kafka的生产者会自动在记录中添加记录的创建时间。

kafka会记录日志追加时间,日志追加时间是指事件保存到broker的时间,如果启用了自动添加时间戳的功能,那么broker会在接收这些记录的时候自动添加时间戳。

【劣势】

1>不支持消息重试,注意区分消息重传!消息消费失败后,把错误记录下来?把消息保存到磁盘上?回调另一个程序?具体哪一种逻辑是由我们决定的,比如发生异常时在catch代码块中加入到死信队列,消息可能丢失(消息来不及处理就宕机了,或者代码逻辑的疏忽)。

2>长时间的消费。kafka只支持pull模式订阅消费,消费者是通过轮询读取消息的,也是通过这个轮询去保持心跳,暂停轮询的时间不能超过几秒,否则会认为consumer退出了consumer group。可以把数据移交给线程池处理,但是最好还是不要长时间消费。

3>重复消息。kafka消费消息是按批次批量消费的,而确认消费成功是通过提交offset来完成的,提交的offset比已经处理的偏移量小,那么提交的offset和已经被处理的offset之间的消息都会被重复消费。

其实重复消息几乎是所有mq都会遇到的问题,kafka避免重复消息可以通过提高offset的提交频度来实现,但是这样就要降低kafka的批量处理性能。(按批次批量处理是kafka高效的主要原因之一,充分利用内存来提高吞吐量)

长时间消费更加容易失败,这种消息的重复消费或者丢失了再消费,会消耗更多时间,kafka不适合长时间消费的场景。

4>消息可能丢失。Kafka通过提交消息偏移量来确认消息的消费,难以保证数据不丢失。

kafka非常适合流式处理、大数据、单次消费时间较短的场合。对于交易系统、订单系统不太适合,但是可以用在商城的日志系统上。

RabbitMQ 

【优势】

1>并发性能极好。

a)本身是用Erlang语言写的,并发性能高。

b)通常消费者中开启多线程,一个channel对应一个消费者,每一个线程把持一个channel,多个线程复用connection的tcp连接,减少性能开销。

c)当rabbitmq队列拥有多个消费者的时候,队列收到的消息将以轮询的分发方式发送给消费者。每条消息只会发送给订阅列表里的一个消费者,不会重复。

这种方式非常适合扩展,而且是专门为并发程序设计的。

2>支持批量确认和异步确认。

RabbitMQ的comfirm机制支持批量确认,每发送一批消息后,调用channer.waitForConfirms方法,等待服务器的确认返回。

RabbitMQ的comfirm机制支持异步取确认,服务器确认了一条或者多条消息后客户端会调这个方法进行处理。

在要求消息发送不丢失的应用场景,设置批量确认和异步确认可以提高吞吐量。

3>支持长时间消费和消息事务。如果消费者没有断开连接,并且没有确认消费,那么rabbitmq会一直等待消费者消费完成。

4>权限控制比较完善。

5>有强大的WEB管理页面。

6>高效持久化。

【劣势】

1>只支持简单集群,对高级集群模式支持不好。

在rabbitmq集群中创建队列,集群只会在单个节点创建队列进程和完整的队列信息(元数据、状态、内容),而不是在所有节点上创建。

这样只有队列的宿主节点,即所有者节点知道队列的所有信息,其他所有者节点只知道队列的元数据和指向该队列的那个节点的指针。

当集群节点崩溃时,该节点的队列进程和关联的绑定都会消失。附加在那些队列上的消费者也会丢失所订阅的信息,任何匹配该队列绑定信息的新消息也都会消失。

rabbitmq分为内存节点和磁盘节点,至少有一个磁盘节点,磁盘节点崩溃了可以发送消息,消费消息,但是无法创建队列、交换器、绑定关系、用户。

引入镜像队列,可以避免单点故障,确保服务的可用性,但是需要人为地为某些重要的队列配置镜像。

新节点加入镜像队列时候,镜像队列的消息不会主动同步到新的slave中,除非调用同步命令,调用同步命令会使得队列阻塞,不能在生产环境中操作。

2>不支持负载均衡,要借助LVS或者HAPROXY等技术实现。

rabbitmq的队列是预先创建在各个节点的,每个队列在节点的分布都是人为控制的,发送消息之前要和其中一台服务器建立连接,所以就会出现不均衡的情况。

要实现负载均衡,三种方式:

a>引入镜像队列。

b>借助LVS或者HAPROXY技术。

c>客户端算法实现。

rabbitmq的负载均衡都是需要我们去做的,工作量不小。

3>只能支持少量堆积,各种队列和元数据的存储需要大量的磁盘空间。

4>Erlang语言开发,研究源码有一定难度。

rabbitmq的特性适合长时间消费的应用场景,比如邮箱通知系统,短信通知系统,不适合大数据的应用场合。

RocketMQ

虽然Kafka支持无限消息堆积,高效的持久化速度,但是对于使用在淘宝交易、订单、充值等场景下还有诸多特性不满足,淘宝团队在借鉴kafka的基础上用Java语言编写了RocketMQ,被广泛应用在订单,交易,充值,流计算,消息推送,日志流式处理,binglog分发等场景。

RocketMQ的并发度和吞吐量比较高,但是不如kafka和zeromq,他的优势主要体现在功能的完备性和系统的可靠性。

【优势】

1>支持消息失败重试、消息事务、消息回溯,高可靠的持久化策略,消息几乎不会丢失。

a)消息重试

消息消费失败的大部分场景下,立即重试99%都会失败,所以rocketmq的重试策略是在消费失败时定时重试,每次时间间隔相同。

发送端的 send 方法本身支持内部重试

接收端的Consumer 消费消息失败后,提供一种重试机制,令消息再消费一次。

b)消息事务

事务成功提交,则消息一定被broker接收。

c)消息回溯

消息写到磁盘,可以基于时间回溯。

2>实时性好。RocketMQ使用长轮询,同Push方式实时性一致,消息的投递延时通常在几个毫秒。

3>支持大量堆积,持久化效率高,批量刷盘。

commitLog文件存放实际的消息数据,每个commitLog上限是1G,满了之后会自动新建一个commitLog文件保存数据。ConsumeQueue队列只存放offset、size、tagcode,非常小,分布在多个broker上,磁盘空间的利用率比较高。

commitLog存放所有实际数据,顺序写消息的效率较高。

RocketMQ累计4K才强制从PageCache中刷到磁盘。

4>对分布式支持很好,使用nameserver管理集群成员,支持动态扩展。

【劣势】

1>存储方式只支持写到磁盘。

a>无法充分利用内存来提高写入读取速度

b>虽然是顺序写,但是随机读,随机读比较慢

Rocketmq的可靠性最高,而且支持大量堆积,对分布式的支持很好,适用于重要业务场合,比如订单系统、物流系统、交易系统、充值系统。

2>使用消息事务,确保了消息的可靠投递,但是必然会导致并发性能下降,这个把双刃剑。

ZeroMQ 
ZeroMQ号称最快的消息队列系统,尤其针对大吞吐量的需求场景

【优势】

1>性能极好,吞吐量极大,并发性能极好,实时性极好。

a) 无锁的队列模型

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

b) 批量处理的算法

 对于传统的消息处理,每个消息在发送和接收的时候,都需要系统的调用,这样对于大量的消息,系统的开销比较大,zeroMQ对于批量的消息,进行了适应性的优化,可以批量的接收和发送消息。

c) 多核下的线程绑定,无须CPU切换

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

2>引用ZeroMQ程序库即可在应用之间发送消息,拿来即用,产品能够快速迭代迅速成型。

ZeroMQ的消息队列对于开发者来说是透明的,开发者只需要发送消息并消费消息,不需要指定某一个队列,甚至感觉不到消息队列的存在,开发过程像socket编程。

ZeroMQ支持三种发送接收方式:点对点模式、发布订阅模式、推拉模式。

点对点模式,绑定地址和建立两端连接即可通信。

发布订阅模式,发布端绑定地址,订阅端与发布端建立连接,即可通信。

推拉模式,推端绑定地址,拉端与推端建立连接。推拉模式与发布订阅模式相比,推拉模型在没有消费者的情况下,发布的消息不会被消耗掉;在消费者能力不够的情况下,能够提供多消费者并行消费解决方案,用于多任务并行处理。

3>可以构建复杂的队列,处理逻辑可以定制。

4>非持久化消息,对系统的存储空间要求不大,但是可以处理成千上万的数据,服务器成本低。

【劣势】

1>消息丢失。

只有消息重传机制,但是不支持消息重试、不支持消息回溯,不支持备份机制,不支持消息事务,不支持持久化,消息丢了就是丢了。

2>资料很少,可借鉴的经验不多,出现问题维护起来比较困难。

3>功能不够完备,很多功能需要我们去实现,不适合复杂的业务。

能满足基本的需求,但是对于其他特殊要求需要我们自己去实现,加大了后期的研发维护成本。

ZeroMQ适合大数据、实时处理、高频计算、定制性强的应用场合,比如股票市场统计。

由于对服务器的要求低,性能极其优越,有利于小型企业的快速应用、软件的快速迭代。

ActiveMQ 
ActiveMQ是Apache下的一个子项目,完全支持JMS1.1和J2EE 1.4规范, 有点对点(p2p)、广播(基于topic的发布-订阅)两种消费方式。

ActiveMQ的下一代产品为Apollo。

【优势】

1>产品成熟,在中等小型规模的场景有很多应用

2>Activemq高版本负载均衡做得比较好,高可用,支持动态扩展。

使用zookeeper管理集群成员,master-slave架构,当master服务器出现故障,slave会顶替成为新的master。

3>功能齐全,支持多种恢复机制,支持事务,支持多种协议。

4>AcitiveMQ很容易嵌入到spring的项目中。

【劣势】

1>存储方式只能支持少量堆积。

ActiveMQ有四种存储器

a)KahaDB message store:是ActiveMQ的默认以及推荐的存储器,特点是基于文件、支持事务日志、可靠、可扩展、速度快等。

可扩展体现在KahaDB支持其他三种存储器的外接扩展,也就是说可以同时用不止一种,这样可以取长补短,适合更广的应用场景,达到性能最佳。

b)AMQ message store:在基于文件、支持事务方面和KahaDB类似。

c)JDBC message store:默认的JDBC驱动是ApacheDerby,同时支持MySQL、PostgreSQL、Oracle、SQLServer、Sybase、Informix、MaxDB等主流的关系数据库。用三张表结构来存储消息,分别是ACTIVEMQ_MSGS、ACTIVEMQ_ACKS、ACTIVEMQ_LOCK。

d)Memory message store:用于实时消息的缓存。

Activemq的存储方式对于hadoop、hdfs、hbase这类分布式系统没有支持。

能够支撑的队列数与消息保存机制有关,Activemq的存储方式决定了他不适合大量队列的场合,也决定了他只能支持少量堆积。

2>ActiveMQ默认的配置性能偏低,需要优化配置,但是配置文件复杂,ActiveMQ本身不提供管理工具,示例代码少。

ActiveMQ适合一般的事务性业务场合,不适合大数据应用的场合。

3>只适合简单集群。

 

你可能感兴趣的:(Kafka、rabbitmq、zeromq、rocketmq、activemq综合对比(二))