Kafka架构

      一个典型的Kafka集群包含若干Producer,若干个Broker,若干个Consumer,以及一个Zookeeper集群,Kafka通过Zookeeper管理集群配置,选举Leader,以及在Consumer Group发生变化时候进行rebalance。Producer使用push模式将消息发布到Broker,Consumer使用pull模式从Broker订阅并消费消息。
      Topic在逻辑上可以被认为是一个queue,每条消费都必须指定他的topic,可以简单的理解为必须指明吧这条消息放进哪个queue里。为了使得Kafka的吞吐率可以线性提高,物理上把Topic分成多个Partition,每个Partition在物理上对应一个文件夹,该文件夹下存储这个Partition的所有消息和索引文件。创建一个Topic时。同时可以指定分区数目,分区越多。起吞吐量也越大,但是需要的资源也越多,同时也会导致更高的不可用性。Kafka在接收到生产者发送的消息之后,会根据均衡策略将消息存储到不同的分区中,因为每一条消息都被append到该Partition中,属于顺序写磁盘,因此效率非常高。
对于一般的Message Queue来说,数据被消费之后就会被删除,但是Kafka一般不会里面把消费过的数据就删除,而是会保留已经消费过的数据。只有在设置的删除策略触发的时候才会删除,Kafka设置了两种删除策略:基于时间和基于Partition文件大小。我们可以通过配置¥KAFKA_HOME/config/server.properties,让Kafka删除一周前的数据。也可以在Partition文件超过1G的时候删除旧数据。如下配置:
Log.retention.hours=168
Log.segment.bytes=1073741824
Log.retention.check.interval.ms=300000
Log.cleaner.enable=false
因为Kafka读取特定消息的时间复杂度为o(1),与文件大小无关,所以这里删除过期文件与提高Kafka性能是没有关系的,选择怎样的删除策略只与具体的需求相关,另外Kafka会为没一个ConsumerGroup保留一些metada信息-当前消费的消息position,也就是offset。这个offset由Consumer控制。正常情况下Consumet会在消费完一条消息后递增该offset。当然Consumer也可以将offset设置成一个较小的值,重新消费一些消息,因为offset完全由Consumer控制,所以Broker是没有状态的,它不需要标记那些消息被消费过,也不需要通过Broker去保证同一个Consumer Group只有一个COnsumer能消费某一条消息,不需要锁的机制,这样就能提高了Kafka的吞吐率。
Producer消息路由
      Producer发送消息到Broker时,会根据Partition机制选择将其存储到哪个Partition.如果Partition机制设置合理,所有消息可以均匀分布到不同的Partition里,这样就实现了负载均衡。如果一个Topic对于一个文件,那这个文件所在的机器I/O就会成为Topic的性能瓶颈,而有了Partition后,不同的消息可以并行写入到不同的Broker的不同Partition里面,极大地提高了吞吐量。可以在¥KAFKA_HOME/config/server.properties中通过num.pritiions来指定新创建Topic的默认Partition数量,也可以在创建Topic是通过参数指定,同时也可以在Topic创建之后通过Kafka提供的工具来修改。在发送一条消息时,可以指定这条消息的key,Producer会根据这个key和Partition机制来判断应该将这条消息发送到哪个Partition。Partition机制可以通过指定Producer的Partition.class这个参数来指定,该class必须实现kafka.producer.pPartitioner接口。
Consumer Group
      使用Consumer high leverAPI时,同一个Topic的一条消息只能被一个Consumer Group内的一个Consumer消费,但是多个Consumer Group可以同时消费这一条消息。
Kafka可以实现消息的广播和单播。一个Topic可以对应多个Consumer Group。如果需要广播,只要每一个Consumer有一个独立的Group就可以了,要实现单播。只需要把所有的Consumer在同一个Group就可以。

上一篇:最佳实践|Apache Pulsar 在华为云物联网之旅


下一篇:生产者消费者模型(实验)