副本机制深入
# 一、副本定义
Kafka的层级是:主题 - 分区 - 副本,副本的概念实际上是在分区层级下定义的,每个分区配置有若干个副本。
所谓副本,本质上就是只能追加消息的的提交日志,同一分区下的副本保存相同的消息,这些副本分散在不同的broker上,来对抗部分 Broker 宕机带来的数据不可用。
# 二、副本角色
数据的同步不可能一蹴而就,如何确保数据已经同步完毕呢?这就需要领导者(Leader-based)的副本机制:
- 在 Kafka 中,副本分成两类:领导者副本(Leader Replica)和追随者副本(Follower Replica)。每个分区在创建时都要选举一个副本,称为领导者副本,其余的副本自动称为追随者副本。
- Kafka 的副本机制比其他分布式系统要更严格一些。在 Kafka 中,追随者副本是不对外提供服务的。这就是说,任何一个追随者副本都不能响应消费者和生产者的读写请求。所有的请求都必须由领导者副本来处理。
- 当领导者副本挂掉了,或者说领导者副本所在的 Broker 宕机时,Kafka 依托于 ZooKeeper 提供的监控功能能够实时感知到,并立即开启新一轮的领导者选举,从追随者副本中选一个作为新的领导者。
追随者副本不处理客户端请求,它唯一的任务就是从领导者副本异步拉取消息,并写入到自己的提交日志中,从而实现与领导者副本的同步。
Kafka副本机制特殊在于只有领导副本提供服务,随从副本负责数据的同步,这样有如下好处:
- Read-your-writes:由于数据同步是一个异步操作,如果随从副本提供读服务,会存在最新消息延迟问题,而只有一个提供服务,就能实现写完之后,立刻能读到自己最新的消息。
- Monotonic Reads(单调读):假设两个随从副本提供读服务,由于两个服从副本同步消息的速度不一样,对于同一个消费者而言,可能会存在读取一个副本的时候有消息,读取另一个副本的时候没消息,而kafka只有主副本提供读写服务,就不会存在这个问题。
# 三、副本的优势
对于一般分布式系统,副本机制有如下好处:
- 提供数据冗余:即使系统部分组件失效,系统依然能够继续运转,因而增加了整体可用性以及数据持久性。
- 提供高伸缩性:支持横向扩展,能够通过增加机器的方式来提升读性能,进而提高读操作吞吐量。
- 改善数据局部性:允许将数据放入与用户地理位置相近的地方,从而降低系统延时。
但是Kafka的副本机制,由于存在领导副本和跟随副本,而且只有领导副本对外提供服务,所以只能提供数据冗余,而提供高伸缩性和改善数据局部性无法提供。
# 四、AR、ISR、OSR
AR
:分区中所有副本称为 ARISR
:所有与主副本保持一定程度同步的副本(包括主副本)称为 ISROSR
:与主副本滞后过多的副本组成 OSR
其中,ISR 不只是追随者副本集合,它必然包括 Leader 副本。甚至在某些情况下,ISR 只有 Leader 这一个副本。
那么如何判断副本是否能够进入ISR呢:这个标准就是 Broker 端参数 replica.lag.time.max.ms 参数值。这个参数的含义是 Follower 副本能够落后 Leader 副本的最长时间间隔,当前默认值是 10 秒。
在上图中,虽然Follower 2副本能落后leader副本,但是只是消息数量相当落后,如果Follower 2同步速率更快,在replica.lag.time.max.ms
间隔时间之内就能完成所有数据的同步,那么Follower 2也是在ISR集合中的。
通过上面的分析,Follower 副本唯一的工作就是不断地从 Leader 副本拉取消息,然后写入到自己的提交日志中。如果这个同步过程的速度持续慢于 Leader 副本的消息写入速度,那么在 replica.lag.time.max.ms 时间后,此 Follower 副本就会被认为是与 Leader 副本不同步的,因此不能再放入 ISR 中。此时,Kafka 会自动收缩 ISR 集合,将该副本“踢出”ISR。
# 五、领导者选举(Unclean Leader Election)
如果ISR为空,说明领导副本挂掉了,那么kafka需要重新选举一个新的leader,而非同步副本落后 Leader 太多,如果选择这些副本作为新副本就可能出现数据的丢失。在kafka配置中,有一个unclean.leader.election.enable
来控制是否允许 Unclean 领导者选举。
- 开启 Unclean 领导者选举可能会造成数据丢失,但好处是,它使得分区 Leader 副本一直存在,不至于停止对外提供服务,因此提升了高可用性。反之,禁止 Unclean 领导者选举的好处在于维护了数据的一致性,避免了消息丢失,但牺牲了高可用性。
- 不开启,相当于这些落后副本无法参与竞选。
建议不要开启它,毕竟我们还可以通过其他的方式来提升高可用性。如果为了这点儿高可用性的改善,牺牲了数据一致性,那就非常不值当了。