Kafka和RocketMQ架构比较

/ RocketMQ / 60浏览

Kafka

物理架构

image-20201108124646755

kafka集群服务器,用于消息的存储、转发。负责接收从生产者发送来的消息并存储,供消费者来获取消息。

消息存储结构

未命名文件

Kafka在创建Topic时,可以指定Topic具有多少个分区,每个分区具有多少个副本。

kafka topic --partitions 3 --replication-factor 2

每个partition会均匀的分布在所有的Broker中。同时每个partition具有多个副本。partition之间是由leader和follower区分的。leader主要用来接收生产者发送的数据和给消费者提供数据。follower主要用来同步leader的消息。

优缺点

优点

  1. 充分利用了集群资源,让每个机器都提供服务

  2. 分区概念,提高消息吞吐量

  3. 伸缩性好

    扩展机器只需要指定集群名称即可。

  4. 顺序写消息,页缓存、零拷贝,降低延时

缺点

  1. 依赖zookeeper,增加维护成本

  2. partition受限于broker

    partition数量大于集群数量时,每个broker中会有多个partition。读写消息时,需要打开多个文件进行操作。

    partition过大时,在broker异常崩溃时,会影响服务可用性。因为该broker中的所有partition将都不可用,需要进行重新选举,leader越多,选举越耗时。

    参考文章:https://www.confluent.io/blog/how-choose-number-topics-partitions-kafka-cluster/

因为partition的受限原因,所以生产者并行性受到影响。

Kafka支持的消息模式:push/pull

RocketMQ

物理架构

NameServer

与Kafka不同的是,RocketMQ并未使用第三方的服务协调框架,而是引用了NameServer来管理集群。NameServer是多个无状态的节点构成,各节点之间无信息通讯。主要工作:

  1. 路由消息

    生产者或消费者能够通过NameServer查找各Topic相应的Broker IP列表分别进行发送消息和消费消息。

  2. 检测集群运行状况

    broker会定期向NameServer以心跳的方式汇报自己的状况。主要包括:

    • Broler的基本信息,如IP、Port
    • topic信息
    • broker集群信息等

    因为Broker主动汇报信息,因此,NameServer不持久化任何数据。也因此导致它是无状态的。

官方原话:

ZooKeeper是Apache的一个开源软件,为分布式应用程序提供协调服务。那为什么 RocketMQ 要自己造轮子,开发集群的管理程序呢?答案是ZooKeeper的功能很强大,包括自动 Master 选举等, RocketMQ 的架构设计决定了它不需要进行 Master 选举,用不到这些复杂的功能,只需要一个轻量级的元数据服务器就足够了。中间件对稳定性要求很高,RocketMQ NameServer 只有很少的代码,容易维护,所以不需 再依赖另一个中间件,从而减少整体维护成本。

Master-Slaver

Kafka的Broker没有主从之分,只有在topic的分区中设计了leader和follower。也正是因为涉及到选举,Kafka引用了ZooKeeper。

RocketMQ部署,是物理上的master和slave节点。topic中没有主从之分。master和slave是多对多的关系。一个master可以拥有多个slave,而一个slave只能拥有一个master。

master节点,会将消息复制到slave节点。写消息时,若master节点挂了,就会直接将消息发到其他master节点,若在读消息的时候出现master节点挂了,就会去slave节点读取消息。(也不一定是master挂了才去slave读取的。)

在Consumer 的配置文件中,并不需要设置是从 Master 读还是从 Slave读,当 Master 不可用或者繁忙的时候, Consumer会被自动切换到从slave读。

消息存储结构

屏幕截图

RocketMQ有两个概念:ConsumeQueue 和 CommitLog。

CommitLog是消息实际存储的物理文件。

ConsumeQueue是消息的逻辑队列,类似于数据库的索引文件,只不过它里面存储的是指向物理存储的地址。

CommitLog

CommitLog 以物理文件的方式存放,它不仅存放了消息内容,还存放了ConsumerQueue内容,每台 Broker上只有一个 CommitLog,且该CommitLog被本机器上所有的ConsumeQueue共享。(一个Broker中只有一个log文件,但有多个逻辑队列。)

在向RocketMQ发送的消息,会被顺序写在CommitLog文件中(顺序写快)。但是读取时,是随机读取的。

ConsumeQueue

ConsumeQueue为RocketMQ中Topic的partition。

服务可靠性保证

由于RocketMQ在搭建环境时,可以是多个Master和多个Slave。因此,在创建 Topic 的时候,把 Topic 的多个Message Queue 创建在多个 Broker 组上。这样当 Broker 组的 Master 不可用后,其他组的Master仍然可用,Producer仍然可以发送消息。所以达到了服务可靠性。

RocketMQ目前还不支持把slave自动转换为master,如果某个master故障,需要将其中一个slave转换为master,需要手动停止slave,通过修改配置文件,来启用为master。

优缺点

优点

  1. 设置MessageQueue概念,增加了吞吐量(吞吐量高)。
  2. 消息存储只有一个文件,存储时完全顺序存储,比Kafka延迟低。
  3. 服务可靠,消息具有强顺序性。kafka在多分区下,消费时会乱序。
  4. 使用自带的NameServer,依赖少
  5. 支持多种消息,如事务消息、严格顺序消息
  6. 消息具有tag,消费者可以根据tag进行消息过滤(不会传递到消费者,减少网络传输)

缺点

  1. 机器资源不能完全利用。

    slave平时一般都不工作(除了同步master数据外),只有在master繁忙的情况下,才对外提供读功能。因此,资源没有完全利用。

  2. 扩展性不好

    kafka在水平扩展时,及其简单。而RocketMQ扩展并不容易。RocketMQ的部署方式有多种。

业务场景

iot数据。多个设备,发送者多,数据采集量大,消费者少,数据要求不丢。采用MQTT协议。

业务消息,发送者少,消费者大。

Kafka和RocketMQ支持的协议都是tcp之上的二进制协议,不支持MQTT。因此,需要有单独的MQTT代理服务来做协议转发。

目前的RabbitMQ使用了routingkey,并赋予它语义,在消费者使用时,过滤其他的routingkey。

对于这个问题,kafka提供了拦截器,需要配置consumer interceptor。RocketMQ提供了tag概念,消费者在消费数据时,服务端会自动过滤掉和tag不匹配的消息。

对于该业务场景,kafka和rocketmq都可以胜任。kafka一般定位于日志消息,rocketmq一般定位于业务消息。例如事务消息、严格顺序消息等场景。且kafka和rocketmq都具有高吞吐低延时的特性。因此,个人感觉,rocketmq可以作为我们业务场景上的消息存储引擎。

关于和MQTT协议代理集成的消息中间件结构如下:

image-20201108212252773

MQTT broker是一个无状态的服务,类似于rocketmq中的NameServer。它不用来存储数据,只需要将MQTT协议转换为RocketMQ消息即可。

image-20201108213616217