1. 基本组成
Kafka集群由若干个Broker组成,Topic由若干个Partition组成,每个Partition里面的消息通过Offset来获取。
-
Broker
当前服务器上的Kafka进程,俗称拉皮条。 只管数据存储,不管是谁生产,不管是谁消费。
一个集群由多个Broker组成,每个Broker都有一个唯一BrokerId,一个Broker可以容纳多个Topic。
每个Cluster当中会选举出一个Broker来担任Controller,负责跟其他Broker进行协调Topic创建、删除,处理Partition的Leader选举,协调Partition迁移等工作。 -
Topic
这是一个逻辑上的概念,Topic是发布的消息的类别。
物理上不同Topic的消息分开存储,一个Topic的消息虽然保存在一个或多个Broker上,但对于用户来说,只需要确定消息的主题Topic即可,生产或消费数据时不需要关心数据存放在何处。 -
Partition
Partition是物理上的概念,为了实现可扩展性,一个Topic可以被分为多个Partition,从而分布到多个Broker上。
Partition中的每条消息都会被分配一个自增Id(Offset)。
Kafka只保证按一个Partition中的顺序将消息发送给消费者,但是不保证单个Topic中的多个Partition之间的顺序。 -
Offset
消息在Topic的Partition中的位置,同一个Partition中的消息随着消息的写入,其对应的Offset也自增,其内部实现原理如下图:
-
Producer
消息生产者,即将消息发布到指定的Topic中,同时Producer也能决定此消息被路由到哪个Partition,比如基于Random(随机)、Round-Robin(轮询)方式或者Hash(哈希)方式等一些算法。 -
Consumer
消息消费者,即想指定的Topic获取消息,根据指定Topic的分区索引及其对应分区上的Offset来获取消息。 -
Consumer Group
每个Consumer都属于一个Consumer group;反过来,每个Consumer Group中可以包含多个Consumer。
如果所有的Consumer都具有相同的Consumer Group,那么消息将会在Consumer之间进行负载均衡。
也就是说一个Partition中的消息只会被相同Consumer Group中某个Consumer消费,每个Consumer Group消息消费是相互独立的。
如果所有的Consumer都具有不同的Consumer Group,则消息将会被广播给所有的Consumer。
Producer、Consumer和Consumer Group之间的关系如下图所示:
-
Replica
副本。Topic的Partition含有N个Replica,N为副本因子。
每个Partition都可以配置至少1个Replica(当仅1个Replication时即仅该Partition本身)
其中一个Replica为Leader,其他都为Follower,Leader处理Partition的所有读写请求,与此同时,Follower会定期地去同步Leader上的数据。 -
ISR(In-Sync Replica)
Replicas的一个子集,表示目前Alive且与Leader能够“Catch-up”的Replicas集合。
由于读写都是首先落到Leader上,所以一般来说通过同步机制从Leader上拉取数据的Replica都会和Leader有一些延迟(包括了延迟时间和延迟条数两个维度),任意一个超过阈值都会把该Replica踢出ISR。
每个Partition都有它自己独立的ISR。 -
Controller
Kafka集群中的其中一个服务器,用来进行Leader Election以及各种Failover。 -
Zookeeper
存放Kafka集群相关元数据的组件 在Zookeeper集群中会保存Topic的状态信息,例如分区的个数、分区的组成、分区的分布情况等。
保存Broker的状态信息。
保存消费者的消费信息。注:从kafka-0.8.2.1版本及以后,kafka的消费者组和offset信息就不存zookeeper了,而是存到broker服务器上
通过这些信息,Kafka很好地将消息生产、消息存储、消息消费的过程结合起来。
2. 拓扑结构
一个典型的Kafka(pre 0.8.2.1)集群拓扑结构如下图所示:
一个简单的消息发送流程如下图所示。
1) Producer根据指定的路由方法(Round-Robin、Hash等),将消息Push到Topic的某个Partition里面。
2) Kafka集群接受到Producer发过来的消息后,将其持久化到硬盘,并保留消息指定时长(可配置),而不关注消费是否被消费。
3) Consumer从Kafka集群Pull数据,并控制获取消息的Offset.
3. zookeeper 节点
kafka 在 zookeeper 中的存储结构如下图所示:
4. Kafka QA
- kafka生产数据时的分组策略
默认是defaultPartition Utils.abs(key.hashCode) % numPartitions
上文中的key是producer在发送数据时传入的,produer.send(KeyedMessage(topic,myPartitionKey,messageContent))
- kafka如何保证数据的完全生产
ack机制:broker表示发来的数据已确认接收无误,表示数据已经保存到磁盘。
0:不等待broker返回确认消息
1:等待topic中某个partition leader保存成功的状态反馈
-1:等待topic中某个partition 所有副本都保存成功的状态反馈
- broker如何保存数据
在理论环境下,broker按照顺序读写的机制,可以每秒保存600M的数据。主要通过pagecache机制,尽可能的利用当前物理机器上的空闲内存来做缓存。
当前topic所属的broker,必定有一个该topic的partition,partition是一个磁盘目录。partition的目录中有多个segment组合(index,log),一个segment有默认的大小是1G。
-
partition如何分布在不同的broker上
broker01 test-0 test-3 broker02 test-1 test-4 broker03 test-2 复制代码
算法: brokers=list.size topic=test partitions=5 list{broker01,broker02,broker03} for(int i=0;i<partitions;i++){ brIndex = i%brokers; hostName = list.get(brIndex) } 复制代码
- consumerGroup的组员和partition之间如何做负载均衡
参考阅读:Kafka的Consumer负载均衡算法
- 如何保证kafka消费者消费数据是全局有序的
伪命题
如果要全局有序的,必须保证生产有序,存储有序,消费有序。
由于生产可以做集群,存储可以分片,消费可以设置为一个ConsumerGroup,要保证全局有序,就需要保证每个环节都有序。
只有一个可能,就是一个生产者,一个partition,一个消费者。这种场景和大数据应用场景相悖。