Kafaka High Level Consumer

来源:互联网 发布:东方财富dk买卖点源码 编辑:程序博客网 时间:2024/06/04 18:38

Kafka解析

www.jasongj.com/2015/01/02/Kafka深度解析

Terminology:

  1. Broker
    Kafka集群包含一个或多个服务器,这种服务器被称为broker
  2. Topic
    每条发布到Kafka集群的消息都有一个类别,这个类别被称为topic。(物理上不同topic的消息分开存储,逻辑上一个topic的消息虽然保存于一个或多个broker上但用户只需指定消息的topic即可生产或消费数据而不必关心数据存于何处)
  3. Partition
    parition是物理上的概念,每个topic包含一个或多个partition,创建topic时可指定parition数量。每个partition对应于一个文件夹,该文件夹下存储该partition的数据和索引文件
  4. Producer
    负责发布消息到Kafka broker
  5. Consumer
    消费消息。每个consumer属于一个特定的consumer group(可为每个consumer指定group name,若不指定group name则属于默认的group)。使用consumer high level API时,同一topic的一条消息只能被同一个consumer group内的一个consumer消费,但多个consumer group可同时消费这一消息。

架构:
这里写图片描述
一个典型的kafka集群中包含若干producer(可以是web前端产生的page view,或者是服务器日志,系统CPU、memory等),若干broker(Kafka支持水平扩展,一般broker数量越多,集群吞吐率越高),若干consumer group,以及一个Zookeeper集群。Kafka通过Zookeeper管理集群配置,选举leader,以及在consumer group发生变化时进行rebalance。producer使用push模式将消息发布到broker,consumer使用pull模式从broker订阅并消费消息。  

Consumer Group
High Level Consumer将从某个Partition读取的最后一条消息的offset存于ZooKeeper中( Kafka从0.8.2版本开始同时支持将offset存于Zookeeper中与将offset存于专用的Kafka Topic中 )。 这个offset基于客户程序提供给Kafka的名字来保存,这个名字被称为Consumer Group。 Consumer Group是整个Kafka集群全局的,而非某个Topic的。 每一个High Level Consumer实例都属于一个Consumer Group,若不指定则属于默认的Group。

Push vs. Pull

  作为一个messaging system,Kafka遵循了传统的方式,选择由producer向broker push消息并由consumer从broker pull消息。一些logging-centric system,比如Facebook的Scribe和Cloudera的Flume,采用非常不同的push模式。事实上,push模式和pull模式各有优劣。
  push模式很难适应消费速率不同的消费者,因为消息发送速率是由broker决定的。push模式的目标是尽可能以最快速度传递消息,但是这样很容易造成consumer来不及处理消息,典型的表现就是拒绝服务以及网络拥塞。而pull模式则可以根据consumer的消费能力以适当的速率消费消息。

Topic & Partition

  Topic在逻辑上可以被认为是一个queue。每条消费都必须指定它的topic,可以简单理解为必须指明把这条消息放进哪个queue里。为了使得Kafka的吞吐率可以水平扩展,物理上把topic分成一个或多个partition,每个partition在物理上对应一个文件夹,该文件夹下存储这个partition的所有消息和索引文件。

Kafka保证同一Consumer Group中只有一个Consumer会消费某条消息,实际上,Kafka保证的是稳定状态下每一个Consumer实例只会消费某一个或多个特定Partition的数据,而某个Partition的数据只会被某一个特定的Consumer实例所消费。 也就是说Kafka对消息的分配是以Partition为单位分配的,而非以每一条消息作为分配单元。 这样设计的劣势是无法保证同一个Consumer Group里的Consumer均匀消费数据,优势是每个Consumer不用都跟大量的Broker通信,减少通信开销,同时也降低了分配难度,实现也更简单。 另外,因为同一个Partition里的数据是有序的,这种设计可以保证每个Partition里的数据可以被有序消费。
总结下来就是:每一个Consumer实例只会消费某一个或多个特定Partition的数据,而某个Partition的数据只会被某一个特定的Consumer实例所消费。

如果某Consumer Group中Consumer(每个Consumer只创建1个MessageStream)数量少于Partition数量,则至少有一个Consumer会消费多个Partition的数据,如果Consumer的数量与Partition数量相同,则正好一个Consumer消费一个Partition的数据。 而如果Consumer的数量多于Partition的数量时,会有部分Consumer无法消费该Topic下任何一条消息。

Consumer Rebalance的算法如下:

将目标Topic下的所有Partirtion排序,存于PT
对某Consumer Group下所有Consumer排序,存于CG,第i个Consumer记为Ci
N=size(PT)/size(CG),向上取整
解除Ci对原来分配的Partition的消费权(i从0开始)
将第i∗N到(i+1)∗N−1个Partition分配给Ci
目前,最新版(0.8.2.1)Kafka的Consumer Rebalance的控制策略是由每一个Consumer通过在Zookeeper上注册Watch完成的。 每个Consumer被创建时会触发Consumer Group的Rebalance,具体启动流程如下:

High Level Consumer启动时将其ID注册到其Consumer Group下,在Zookeeper上的路径为/consumers/[consumer group]/ids/[consumer id]
在/consumers/[consumer group]/ids上注册Watch
在/brokers/ids上注册Watch
如果Consumer通过Topic Filter创建消息流,则它会同时在/brokers/topics上也创建Watch
强制自己在其Consumer Group内启动Rebalance流程
在这种策略下,每一个Consumer或者Broker的增加或者减少都会触发Consumer Rebalance。 因为每个Consumer只负责调整自己所消费的Partition,为了保证整个Consumer Group的一致性,当一个Consumer触发了Rebalance时,该Consumer Group内的其它所有其它Consumer也应该同时触发Rebalance。

http://www.infoq.com/cn/articles/kafka-analysis-part-4

原创粉丝点击