常用的MQ比较

一、资料文档

Kafka:中,有Kafka作者自己写的书,网上资料也有一些

rabbitMq:多,有一些不错的书,网上资料多

rocketmq:少,没有专门写rocketmq的书,网上的资料良莠不齐,官方文档很简洁,但是对技术细节没有过多的描述。

activemq:多,没有专门写activemq的书,网上资料多

二、开发语言

Kafka:Scala

rabbitmq:Erlang

rocketmq:java

activemq:java

三、支持的协议

Kafka:自己定义的一套…(基于TCP)

rabbitmq:AMQP

rocketmq:自己定义的一套…

activemq:OpenWire、STOMP、REST、XMPP、AMQP

四、消息存储

Kafka:内存、磁盘、数据库,支持大量堆积。

  1. Kafka的最小存储单元是分区,一个topic包含多个分区,kafka创建主题时,这些分区会被分配在多个服务器上,通常一个broker一台服务器
  2. 分区首领会均匀的分布在不同的服务器上,分区副本也会均匀的分布在不同的服务器上,确保负载均衡和高可用性,当新的broker加入集群的时候,部分副本会被移动到新的broker上
  3. 根据配置文件的目录清单,kafka会把新的分区分配给目录清单里分区数最少的目录
  4. 默认情况下,分区器使用轮询算法把消息均衡的分布在同一个主题的不同分区种,对于发送指定了key的情况,会根据key的hashcode取模后的值存到对应的分区种

rabbitmq:内存、磁盘,只是少量堆积。

  1. rabbitmq的消息分为持久化的消息和非持久化消息,不管是持久化的消息还是非持久化的消息都可以写入到磁盘
  2. 持久化的消息在到达队列时就写入磁盘,并且如果可以,持久化的消息也会在内存中保存一份备份,这样可以提高一定的性能,当内存吃紧的时候会从内存中清除,非持久化消息一般只存于内存中,在内存吃紧的时候会被换入到磁盘中,以节省内存
  3. 引入镜像队列机制,可将重要队列”复制“到集群中的其他broker上,保证这些队列不会丢失。配置镜像的队列,都包含一个主节点master和多个从节点slave,如果master失效,加入时间最长的slave会被提升为新的maste,除发送消息外的所有动作都向master发送,然后由master将命令执行结果广播给各个slave,保证负载均衡和高可用性

rocketmq:磁盘,支持大量堆积

  1. commitLog文件存放实际的消息数据,每个commitLog上限是1G,满了之后会自动新建一个commitLog文件保存数据,Consumeueue队列只存放offset、size、tagcode,非常小,分布在多个broker上,ConsumeQueue相当于CommitLog的索引文件,消费者消费时会从consumeQueue中查找消息在commitLog中的offset,再去commitLog中查找元数据。
  2. ConsumeQueue存储格式的特性,保证了写过程的顺序写盘(写CommitLog文件),大量数据IO都在顺序写同一个commitLog,满1G再写新的,加上rocketmq时累计4K才强制从PageCache中刷到磁盘(缓存),所以高并发写性能突出。

activemq:内存、磁盘、数据库,支持少量堆积

五、消息事务

Kafka:支持

rabbitmq:支持

客户端将信道设置为事务模式,只有当消息被rabbitmq接收,事务才能提交成功,否则在捕获异常后进行回滚,使用事务会示得性能有所下降

rocketmq:支持

activemq:支持

六、负载均衡

Kafka:支持负载均衡

  1. 一个broker通常就是一台服务器节点。对于同一个Topic的不同分区,Kafka会尽力将这些分区分不到不同的Broker服务器上,zookeeper保存了broker、主题和分区的元数据信息,分区首领会处理来自客户端的生产请求,kafka分区首领会被分配到不同的broker服务器上,让不同的broker服务器共同分担任务。
    1. 每一个broker都缓存了元数据信息,客户端可以从任意一个broker获取元数据信息并缓存起来,根据元数据信息知道要往哪里发送请求。
  2. kafka的消费者组订阅同一个topic,会尽可能的使得每一个消费者分配到相同数量的分区,分担负载。
  3. 当消费者加入或者退出消费者组的时候,还会触发在均衡,为每一个消费者重新分配分区,分摊均衡
    1. kafka的负载均衡大部分时自动完成的,分区的创建也是kafka完成的,隐藏了很多细节,避免了繁琐的配置和认为疏忽造成的负载问题。
  4. 发送段由topic和key来决定消息发往哪个分区,如果key为null,那么会使用轮询算法将消息均衡的发送到同一个tipic的不同分区中,如果key不为null,那么会根据key的hashcode取模计算除要发往的分区。

rabbitmq:对负载均衡的支持不好

  1. 消息被投递到哪个队列是由交换机和key决定的,交换器、路由键、队列都需要手动创建。

    1. rabbitmq客户端发送消息要和broker建立连接,需要事先知道broker上有哪些交换器,有哪些队列。通常声明要发送的目标队列,如果没有目标队列,会在broker上创建一个队列,如果有,就什么都不处理,接着往这个队列发送消息。假设大部分繁重任务的对立的都创建在同一个broker上,那么这个broker的负载就会过大。(可以在上线前预先创建队列,无需声明要发送的队列,但是发送时不会尝试创建队列,可能出现找不到队列的问题,rabbitmq的备份交换器会把找不到队列的消息保存到一个专门的队列中,以便以后查询使用)
    2. 使用镜像队列机制建立rabbitmq集群可以解决这个问题,形成master-slave的架构,master节点会均匀分布在不同的服务器上,让每一台服务器分摊负载。slave节点只是负责转发,在master失效时会选择加入时间最长的slave成为master。
    3. 当新节点加入镜像队列的时候,队列中的消息不会同步到新的slave中,除非调用同步命令,但是调用命令后,队列会阻塞,不能再生产环境中调用同步命令。
  2. 当rabbitmq队列拥有多个消费者的时候,队列收到的消息将以轮询的分发方式发送给消费者。每条消息只会发送给订阅列表里的一个消费者,不会重复。

    1. 这种方式非常适合扩展,而且是专门为并发程序设计的。
    2. 如果某些消费者的任务比较繁重,那么可以设置basicQos限制信道上消费者能保持的最大未确认消息的数量,在达到上限时,rabbitmq不再向这个消费者发送任何消息。
  3. 对于rabbitmq而言,客户端与集群建立的TCP连接不是与集群中所有的节点建立连接,而是挑选其中一个节点建立连接

  4. 但是rabbitmq集群可以借助HAProxy、LVS技术,或者在客户端使用算法实现负载均衡,引入负载均衡之后,各个客户端的连接可以分摊到集群的各个节点之中。

#客户端负载均衡算法:
1、轮询法:按顺序返回下一个服务器的连接地址。

2、加权轮询法:给配置高、负载低的机器配置更高的权重,让其处理更多的请求;而配置低、负载高的机器,给其分配较低的权重,降低其系统负载。

3、随机法:随机选取一个服务器的连接地址。

4、加权随机法:按照概率随机选取连接地址。

5、源地址哈希法:通过哈希函数计算得到的一个数值,用改数值对服务器列表的大小进行取模运算。

6、最小连接数法:动态选择当前连接数最少的一台服务器的连接地址。

rocketmq:支持负载均衡

一个broker通常时一个服务器节点,broker分为master和slave,master和slave存储的数据一样,slave从master同步数据

  1. nameserver与每个集群成员保持心跳,保存着Topic-Broker路由信息,同一个topic的队列会分布在不同的服务器上。

  2. 发送消息通过轮询队列的方式发送,每个队列接收平均的消息量,发送消息指定topic、tags、keys,无法指定投递到哪个队列(没有意义,集群消费和广播消费跟消息存放在哪个队列没有关系)。

    1. tags选填,类似于gmail为每封邮件设置的标签,方便服务器过滤使用。目前只支持每个消息设置一个tag,所以也可以类比为Notify的MessageType概念。
    2. keys选填,代表这条消息的业务关键词,服务器会根据keys创建哈希索引,设置后,可以在Console系统根据Topic、Keys来查询消息,由于是哈希索引,请尽可能保证key唯一,例如订单号,商品id等。
  3. rocketmq的负载均衡策略规定,Consumer数量应该小于Queue数量,如果Consumer超过Queue数量,那么多余的Consumer将不能消费消息。这一点和kafka是一致的,rocketmq会尽可能地为每一个Consumer分配相同数量的队列,分摊负载。

七、集群方式

Kafka:天然的Leader-Slave无状态集群,每台服务器既是Master也是Slave。

  1. 分区首领均匀的分布在不同的kafka服务器上,分区副本也均匀的分布在不同的kafka服务器上,所以每一台kafka服务器既含有分区首领,同时又含有分区副本,每一台kafka服务器是某一台kafka服务器的Slave,同时也是某一台kafka服务器的leader。

  2. afka的集群依赖于zookeeper,zookeeper支持热扩展,所有的broker、消费者、分区都可以动态加入移除,而无需关闭服务,于不依靠zookeeper集群的mq相比,这是最大的优势。

rabbitmq:支持简单集群,‘复制’模式,对高级集群模式支持不好。

  1. rabbitmq的每一个节点,不管是单一节点系统或者是集群中的一部分,要么是内存节点,要么是磁盘节点,集群中至少要有一个是磁盘节点。
  2. 在rabbitmq集群中创建队列,集群直会在单个节点创建队列进程和完整的队列信息(元数据、状态、内容),而不是在所有节点上创建。
  3. 引入镜像队列,可以避免单点故障,确保服务的可用性,但是需要认为的为某些重要的队列配置镜像。

rocketmq:常用多对‘master-slave’模式,开源版本需要手动切换slave变成master

NameServer是一个几乎无状态节点,可集群部署,节点之间无任何信息同步。

  1. Broker部署相对复杂,Broker分为Master与Slave,一个Master可以对应多个Slave,但是一个Slave只能对应一个Master,Master与Slave的对应关系通过指定相同的BrokerName,不同的BrokerId来定义,BrokerId为0表示Master,非0表示Slave。Master也可以部署多个。每个Broker与NameServer集群中的所有节点建立长连接,定时注册Topic信息到所有NameServer。
  2. Producer与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从NameServer取Topic路由信息,并向提供Topic服务的Master建立长连接,且定时向Master发送心跳。Producer完全无状态,可集群部署。
  3. Consumer与NameServer集群中的其中一个节点(随即线则)建立长连接,定期从NameServer取Topic路由信息,并向提供Topic服务的Master、Slave建立长连接,且定时向Master、Slave发送心跳。COnsumer既可以从Master订阅消息,也可以从Slave订阅消息,订阅规则由Broker配置决定。
  4. 客户端先找到NameServer,然后通过NameServer再找到Broker。
  5. 一个topic有多个队列,这些队列会均匀的分布再不同的broker服务器上。rocketmq队列的概念和kafka的分区概念是基本一致的,kafka同一个topic的分区尽可能的分布再不同的broker上,分区副本也会分布再不同的broker上。
  6. rocketmq集群的slave会从master拉去数据备份,master分布再不同的broker上。

activemq:支持简单集群模式,比如‘主-备’,对高级集群模式支持不好

八、管理界面

Kafka:一般

rabbitmq:好

rocketmq:无,网上有支持的console 项目下载可支持

activemq:一般

九、可用性

Kafka:非常高(分布式)

rabbitmq:高(主从)

rocketmq:非常高(分布式)

activemq:高(主从)

十、消息重复

Kafka:支持at least once(最少消费一次)、at most once(最多一次)

rabbitmq:支持at least once、at most once

rocketmq:支持at least once

activemq:支持at least once

十一、吞吐量TPS

Kafka:极大

Kafka按批次发送消息和消费消息。发送端将多个小消息合并,批量法向Broker,消费端每次取出一个批次的消息批量处理。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值