Kafka-分区复制
复制功能是kafka架构的核心。kafka对自己的描述:一个分布式的、可分区的、可复制的提交日志服务。
复制之所以那么关键,是因为它可以在个别节点失效时仍能保证kafka的可用性和持久性。
kafka使用主题来组织数据,每个主题被分为若干个分区,每个分区有多个副本。那些副本被保存在broker上,每个broker可以保存成百上千个属于不同主体和分区的副本。
副本有两种类型
首领副本:每个分区都有一个首领副本。为了保证一致性,所有生产者请求和消费者请求都会经过这个副本。
跟随者副本:首领以外的副本都是跟随者的副本。跟随者副本不处理来自客户端的请求,它们唯一的任务就是从首领那里复制消息,保持与首领一致的状态。如果首领发生崩溃,其中的一个跟随者会被提升为新首领。
首领的另一个任务时搞清楚哪个跟随者的状态是一致的。跟随者为了保持与首领的状态一致,在有新消息到达时尝试从首领那里复制消息,不过有各种原因会导致同步失败,如网络拥塞导致复制变慢,broker发生崩溃导致复制滞后,直到重启broker后复制才会继续。
为了与首领保持同步,跟随者向首领发送获取数据的请求,这种请求与消费者为了读取消息而发送的请求是一样的。首领将相应消息发送给跟随者。请求消息里包含了跟随者想要获取消息的偏移量,而且这些偏移量总是有序的。
一个跟随者副本先请求消息1,接着请求消息2,然后请求消息3,在收到这3个请求的相应之前,它是不会发送第四个请求消息的。如果跟随者发送了请求消息4,那么首领就会知道它已经收到了前面3个请求的相应。通过查看每个跟随者请求的最新偏移量,首领就会知道每个跟随者复制的进度。如果跟随者在10s内没有请求任何消息,或者虽然在请求消息,但在10s内没有请求最新的数据,那么它就会被认为是不同步的。如果一个副本无法与首领保持一致,在首领发生失效时,它就不可能成为新首领--毕竟它没有包含全部的消息。
持续请求得到的最新消息副本被称为同步的副本。在首领发生失效时,只有同步副本才有可能被选为新首领。
跟随者的正常不活跃时间或者在成为不同步副本之前的时间是通过replica.lag.time.max.ms参数来配置的。这个时间间隔直接影响着首领选举期间的客户端行为和数据保留机制。
除了当前首领之外,每个分区都有一个首选首领--创建主题时选定的首领就是分区的首选首领。之所以叫做首选首领,是因为在创建分区时,需要在broker之间均衡首领。因此,我们希望首选首领在成为真正的首领时,broker间的负载最终会得到均衡。默认情况下,kafka的auto.leader.rebalance.enable被设为true,它会检查首选首领是不是当前首领,如果不是,并且该副本是同步的,那么就会触发首领选举,让首选首领成为当前首领。
从分区的副本清单里可以很容易找到首选首领。清单里的第一个副本一般就是首选首领。不管当前首领是哪一个副本,都不会改变这个事实,即使使用副本分配工具将副本重新分配给其它broker。如果手动进行副本分配,第一个指定的副本就是首选首领,所以要确保首选首领被传播到其它broker上,避免让包含了首领的broker负载过重,而其它broker却无法为他们分担负载。