(︶^︶)

ActiveMQ

ActiveMQ作为传统型消息中间件,严格遵循JMS规范,功能全面,安装简单,需要的资源少。但是性能较差,不支持高并发和数以亿计的消息缓存,容错和扩展性差,不支持重复消费,不支持批处理。

Kafka

Kafka 的优点

1、消息持久化
以时间复杂度为O(1)的方式提供消息持久化能力,即使对TB级以上数据也能保证常数时间复杂度的访问性能。
2、高性能 高吞吐率
即使在非常廉价的商用机器上也能做到单机支持每秒100K条以上消息的传输,支持batch 操作。
3、消息分区 分布式消费
支持Kafka Server间的消息分区,及分布式消费,同时保证每个Partition内的消息顺序传输。同时支持离线数据处理和实时数据处理(Kafka Stream)。
4、分布式可扩展
支持在线水平扩展(Scale out),Kafka 集群可以透明的扩展,增加新的服务器进集群。
5、高容错
Kafka每个Partition的数据都会复制到几台服务器上。当某个Broker故障失效时,ZooKeeper服务将通知生产者和消费者,生产者和消费者转而使用其它Broker。

Kafka 的不足

1、重复消息
Kafka 只保证每个消息至少会送达一次,虽然几率很小,但一条消息有可能会被送达多次。
2、消息乱序
虽然一个Partition 内部的消息是保证有序的,但是如果一个Topic 有多个Partition,Partition 之间的消息送达不保证有序。
3、复杂性
Kafka需要 zookeeper 集群的支持,Topic通常需要人工来创建,部署和维护较一般消息队列成本更高。

相比RocketMQ,Kafka的不足之处还在于

生产者发布消息的并行性受到分区数量的限制
消费者消费并行度的程度也受到消费分区数量的限制。 假设分区数量为20,并发消费使用者的最大数量为20。每个主题由固定数量的分区组成。 分区号决定了单个代理在不明显影响性能的情况下可以拥有的最大主题数量。

为什么Kafka无法支持更多的分区?
每个分区存储整个消息数据。 尽管每个分区都按顺序写入磁盘,但随着并发写入分区数量的增加,写入在操作系统的角度上变得随机。由于分散的数据文件,使得 Kafka 很难使用Linux IO组提交机制。

一般来说,Kafka集群中存在的分区越多,可以达到的吞吐量就越高,在某些情况下,分区太多也可能会产生负面影响。
(1)更多分区需要更多打开的文件句柄
(2)更多分区可能会增加不可用性
(3)更多分区可能会增加端到端延迟
(4)更多的分区可能需要更多的客户端内存
具体分析看这里

RocketMQ

为何RocketMQ能支持更多的分区?

img
1、所有的消息数据都存储在提交日志文件中。所有写入都是完全顺序的,而读取是随机的。
2、ConsumeQueue存储实际用户消费位置信息,这些信息也以顺序方式刷新到磁盘。

优点:

  1. 每个消费队列都是轻量级的,并且包含有限的元数据。
  2. 对磁盘的访问是完全顺序的,这可以避免磁盘锁争用,并且在创建大量队列时不会导致高磁盘IO等待。

缺点:

  1. 消息消耗将首先读取消耗队列,然后提交日志。这个过程在最坏的情况下会带来一定的成本。
  2. 提交日志和消耗队列需要在逻辑上一致,这给编程模型带来了额外的复杂性。

设计动机:

  1. 随机阅读。尽可能多地读取以增加页面缓存命中率,并减少读取IO操作。所以大的内存仍然是可取的。如果大量消息累积,读取性能会严重下降吗?答案是否定的,原因如下:
    (1) 即使消息的大小仅为1KB,系统也会提前读取更多数据,请参阅PAGECACHE预取以供参考。这意味着对于后续数据读取,它将访问将要执行的主存储器,而不是慢速磁盘IO读取。
    (2) 从磁盘随机访问提交日志。如果在SSD的情况下将 I/O 调度器设置为NOOP,则读取的QPS将大大加速,因此比其他电梯调度器算法快得多。
  2. 由于ConsumeQueue只存储固定大小的元数据,主要用于记录消费进度,所以随机读取得到很好的支持。利用页面缓存(PageCache)预取功能,访问ConsumeQueue的速度与访问主内存一样快,即使是在大量消息积累的情况下。因此,ConsumeQueue不会对阅读性能造成显着的损失。
  3. CommitLog存储几乎所有的信息,包括消息数据。与关系数据库的重做日志类似,只要提交日志存在,消费队列,消息密钥索引和所有其他所需数据都可以完全恢复。

RocketMQ vs. ActiveMQ vs. Kafka

img