Kafka Controller:它负责管理整个集群中所有分区和副本的状态等工作。比如当某个分区的leader副本出现故障时,由控制器负责为该分区选举新的leader副本。再比如当检测到某个分区的ISR集合发生变化时,由控制器负责通知所有broker更新其元数据信息。
kafka Controller 选举:在Kafka集群中会有一个或多个broker,其中有一个broker会被选举为控制器(Kafka Controller)。
ISR:
“in-sync” replicas,每个Partition有一个leader与多个follower,leader会维护一个与其基本保持同步的Replica列表,该列表称为ISR(in-sync Replica),每个Partition都会有一个ISR,而且是由leader动态维护。如下方式可以查到分区的Isr:
./bin/kafka-topics --zookeeper kafka-node-01:2181 --describe --topic test-001
Topic:test-001 PartitionCount:5 ReplicationFactor:2 Configs:
Topic: test-001 Partition: 0 Leader: 2 Replicas: 2,1 Isr: 2,1
Topic: test-001 Partition: 1 Leader: 3 Replicas: 3,2 Isr: 2,3
Topic: test-001 Partition: 2 Leader: 4 Replicas: 4,3 Isr: 3,4
Topic: test-001 Partition: 3 Leader: 5 Replicas: 5,4 Isr: 5,4
Topic: test-001 Partition: 4 Leader: 1 Replicas: 1,5 Isr: 1,5
分区理解:
Kafka会将接收到的消息进行分区(partition),每个主题(topic)的消息有不同的分区,为了保证高可用,每个分区都会有一定数量的副本(replica)。这样如果有部分服务器不可用,副本所在的服务器就会接替上来,保证应用的持续性。
为了保证较高的处理效率,消息的读写都是在固定的一个副本上完成,这个副本就是所谓的Leader,而其他副本则是Follower,而Follower则会定期地到Leader上同步数据。
如果某个分区所在的服务器出了问题,不可用,kafka会从该分区的其他的副本中选择一个作为新的Leader。之后所有的读写就会转移到这个新的Leader上。现在的问题是应当选择哪个作为新的Leader。显然,只有那些跟Leader保持同步的Follower才应该被选作新的Leader。
如果没有一个Leader,所有Replica都可同时读/写数据,就无法保证数据的一致性和有序性。而引入Leader后,只有Leader负责数据读写,Follower只向Leader顺序Fetch数据(N条通路),系统更加简单且高效。
Kafka会在Zookeeper上针对每个Topic维护一个称为ISR(in-sync replica,已同步的副本)的集合,该集合中是一些分区的副本。只有当这些副本都跟Leader中的副本同步了之后,kafka才会认为消息已提交,并反馈给消息的生产者。如果这个集合有增减,kafka会更新zookeeper上的记录。
只有副本跟Leader同步后,才加入ISR列表。
如果某个分区的Leader不可用,Kafka就会从ISR集合中选择一个副本作为新的Leader。
显然通过ISR,kafka需要的冗余度较低,可以容忍的失败数比较高。假设某个topic有f+1个副本,kafka可以容忍f个服务器不可用。
分区leader副本的选举:
- 当创建分区(创建主题或增加分区都有创建分区的动作)或分区上线(比如分区中原先的leader副本下线,此时分区需要选举一个新的leader上线来对外提供服务)的时候都需要执行leader的选举动作。
- 当分区进行重分配(reassign)的时候也需要执行leader的选举动作。
- 当某节点被优雅地关闭(也就是执行ControlledShutdown)时,位于这个节点上的leader副本都会下线,所以与此对应的分区需要执行leader的选举。
如果当一个broker停止或者crashes时,所有本来将它作为leader的分区将会把leader转移到其它broker上去。这意味着当这个broker重启时,它将不再担任何分区的leader,kafka的client也不会从这个broker来读取消息,从而导致资源的浪费,并且可能造成各个节点负载不均衡。
比如下面的broker 7是挂掉重启的,我们可以发现Partition 1虽然在broker 7上有数据,但是由于它挂了,所以kafka重新将broker 3当作该分区的Leader,然而broker 3已经是Partition 6的Leader了。
[iteblog@www.iteblog.com ~]$ kafka-topics.sh --topic iteblog \
--describe --zookeeper www.iteblog.com:2181
Topic:iteblog PartitionCount:7 ReplicationFactor:2 Configs:
Topic: iteblog Partition: 0 Leader: 1 Replicas: 1,4 Isr: 1,4
Topic: iteblog Partition: 1 Leader: 3 Replicas: 7,3 Isr: 3,7
Topic: iteblog Partition: 2 Leader: 5 Replicas: 5,7 Isr: 5,7
Topic: iteblog Partition: 3 Leader: 6 Replicas: 6,1 Isr: 1,6
Topic: iteblog Partition: 4 Leader: 4 Replicas: 4,2 Isr: 4,2
Topic: iteblog Partition: 5 Leader: 2 Replicas: 2,5 Isr: 5,2
Topic: iteblog Partition: 6 Leader: 3 Replicas: 3,6 Isr: 3,6
系统默认配置了auto.leader.rebalance.
enable
=true,自动平行leader,如果设置为flase,就需要手工执行
kafka-preferred-replica-election.sh脚步来平行一次leader。详细
参考:Kafka集群Leader均衡(Balancing leadership)
下面是Leader平衡的结果:
[iteblog@www.iteblog.com ~]$ kafka-topics.sh --topic iteblog --describe \
--zookeeper www.iteblog.com:2181
Topic:iteblog PartitionCount:7 ReplicationFactor:2 Configs:
Topic: iteblog Partition: 0 Leader: 1 Replicas: 1,4 Isr: 1,4
Topic: iteblog Partition: 1 Leader: 7 Replicas: 7,3 Isr: 3,7
Topic: iteblog Partition: 2 Leader: 5 Replicas: 5,7 Isr: 5,7
Topic: iteblog Partition: 3 Leader: 6 Replicas: 6,1 Isr: 1,6
Topic: iteblog Partition: 4 Leader: 4 Replicas: 4,2 Isr: 4,2
Topic: iteblog Partition: 5 Leader: 2 Replicas: 2,5 Isr: 5,2
Topic: iteblog Partition: 6 Leader: 3 Replicas: 3,6 Isr: 3,6
可以看出broker 7重新变成Partition 1的Leader了。
其他:
replica
分布式系统必然要实现高可靠性,而目前实现的主要途径还是依靠冗余机制——简单地说,就是备份多份日志。这些备份日志在Kafka中被称为副本(replica),它们存在的唯一目的就是防止数据丢失。
副本分为两类:领导者副本(leader replica)和追随者副本(follower replica)。follower replica 是不能提供服务给客户端的,也就是说不负责响应客户端发来的消息写入和消息消费请求。它只是被动地向领导者副本(leader replica)获取数据,而一旦leader replica所在的broker宕机,kafka会从剩余的replica中选举出新的leader继续提供服务。
ISR
ISR的全称是in-sync replica,翻译过来就是与leader replica保持同步的replica集合。这是一个特别重要的概念。前面讲了很多关于Kafka的副本机制,比如一个partition可以配置N个replica,那么这是否就意味着该partition可以容忍N-1个replica失效而不丢失数据呢?答案是“否”!
Kafka为partition动态维护一个replica集合。该集合中的所有replica保存的消息日志都与leader replica保持同步状态。只有这个集合中的replica才能被选举为leader,也只有该集合中所有replica都接收到了同一条消息,kafka才会将该消息置于“已提交”状态,即认为这条消息发送成功。回到刚才的问题,Kafka承诺只要这个集合中至少存在一个replica,那些“已提交”状态的消息就不会丢失——记住这句话的两个关键点:①ISR中至少存在一个“活着的”replica;②“已提交”消息。
正常情况下,partition的所有replica(含leader replica)都应该与leader replica保持同步,即所有replica都在ISR中。因为各种各样的原因,一小部分replica开始落后于leader replica的进度。当滞后到一定程度时,Kafka会将这些replica“踢”出ISR。相反地,当这些replica重新“追上”了leader的进度时,那么Kafka会将它们加回到ISR中。这一切都是自动维护的,不需要用户进行人工干预,因而在保证了消息交付语义的同时还简化了用户的操作成本。
更多参考:
https://blog.csdn.net/u013256816/article/details/89369160