分享

Kafka实战之生产环境硬盘问题应急处理




问题导读:

1、怎样才能将损失降到最低?
2、怎样避免数据全部丢失的情况?
3、如何选举其他副本为Leader?




问题描述
当事人的问题描述

640.jpeg

当事人描述

问题整理

  • Broker 1004 上面的一块磁盘坏掉了。
  • 坏的透透的,也没有RAID,反正就是这块磁盘数据恢复不了了。
  • 因为1004坏了,导致副本离线,如果副本刚好是Leader,则会触发Leader重选举。
  • 然后刚好有一些分区中的ISR只有1004,这个时候1004副本下线,重选举的时候Leader选不出来,就变成了-1,这些分区此时为不可用状态,需要里面恢复。
  • 如果直接停机1004更换磁盘重启,那么势必会造成数据全部丢失、
  • 分区都是3副本


❝
应该怎么办?才能将损失降到最低啊!

分析问题

磁盘不是RAID,不能容错,想恢复数据是不大可能了,这里我们不考虑其他一些方式恢复磁盘。

一般来说,Kafka的多副本就是用来应对这种情况的,Follower副本用来备份容错,这里分区都是3个副本,既然1004中的副本丢失了,没有关系,还有其他副本的数据。

但是坏就坏在,有一些分区的Follower不在ISR里面,ISR表示的是同步副本,跟Leader保持较高的同步,如果配合ack=all,可以达到最高的可靠性。

ISR里面只有1004,如果贸然停机1004,换上新盘,再重启会造成什么情况?

❝
会造成数据全部丢失

当1004再次重启的时候,他会再次当选为Leader, 那么其他的Follower副本就会去同步Leader,发现自己的数据跟Leader不一致就会截断自己的数据,这个时候Leader没有数据,Follower截断之后,那就全没了。

那我让其他副本当选为Leader是不是就可以避免上面的问题了?

嗯,没错,为了避免上面的问题,我们只能先让其他的副本当选Leader了。

❝
那么,如何选举其他副本为Leader呢?

  • 所有的选举策略最基本的逻辑是副本在线&&副本在ISR内,但是有一种情况例外
当配置了脏选举,或者主动执行脏选举命令的时候,不在ISR内也可以当选,所以执行一次脏选举就可以。
  • 手动修改ISR里面的数据


解决问题

解法一:

  • 停止Broker-1004,换上新的磁盘
  • 执行一次脏选举kafka-leader-election.sh --UNCLEAN
  • 执行完毕之后,会从之前的Follower副本里面选出一个作为Leader
  • 稍等片刻,等1004掉出ISR列表之后,再重启1004这台机器。
  • 1004重启之后,开始向Leader同步数据,因为是新的磁盘,还没有任何数据,会自动重建。


这里有几个点需要大家思考一下:

❝
当上面步骤3执行完毕之后,新的Leader选出来了,作为原来就在ISR列表中的 broker-1004 会掉出ISR列表吗?

答案是 “会” ! 这里涉及到ISR的伸缩机制。

简单来说就是,每个Broker都会有一个isr-expiration缩小定时任务,定时去检查是否满足ISR缩小的条件,每隔replica.lag.time.max.ms/2 (2.5版本开始默认30000)毫秒执行一次

其中一个条件就是,找到当前Broker所有在线的Leader分区

回到我们这个问题,当新的Leader选举出来之后,启动了定时任务之后,就会发现之前在ISR列表内的1004,已经慢慢脱离ISR

有同学表示,是否可以指定某个副本当选Leader,比如Follower副本中我想挑选一个最大LEO当选Leader,是不是可以将损失降到更低!

解法二:

❝
Follower副本中我想挑选一个最大LEO当选Leader,是不是可以将损失降到更低!

首先,能用这种方案,那么前提肯定acks!=all

因为ack==all的情况,已经确保了isr列表里面的的数据都是一致的。

但是话又说回来,你既然acks!=all,也就相当于你已经允许一定量的数据发生丢失。

所以丢多一点和丢少一点很重要吗(极小的差别)

官方Leader选举策略都是按照AR的顺序来选择,是因为它需要保证Leader的均衡(为何是保证的leader均衡请看分区副本分配策略), 这才是首要的,想要确保数据不丢失请设置acks=all

另外,判断Follower的LEO大小,是需要在源码层级调用才知道,那么就需要改源码了。

你想通过recovery-point-offset-checkpoint来判断LEO的大小是不准确的,这个是记录的分区写入磁盘的offset,每个Broker写入时机你也不清楚(操作系统控制什么时候将PageCache写入磁盘),所以不能保证100%的准确性。

那你说,你一定要这样做(可以但没有必要),那我也给你提供这么一个思路。(非源码层面的)

  • 停止Broker-1004,换上新的磁盘
  • 从Broker中找到你想要这么做的分区,查看recovery-point-offset-checkpoint文件比较一下,找到最大LEO的副本,这里你可能会有很多个分区
  • 修改zk中/brokers/topics/{Topic名称}/partitions/{分区号}/state节点,把ISR改成只剩下你想要设为leader的副本id。
  • 因为Controller平时不会监听state节点,所以你还需要再创建一个/isr_change_notification/isr_change_序号节点,触发Controller的监听,让他能触发Controller更新内存,还有给brokers发送UpdateMetadata请求

例如: /isr_change_notification/isr_change_0000000001

// 这个表示的是 Topic2的0号分区 有ISR的变更

  1. {"version":1,"partitions":[{"topic":"Topic2","partition":0}]}
复制代码

  • 改了ISR之后,仍旧不会触发Leader选举,所以这个时候我们可以手动触发一下kafka-leader-election.sh --UNCLEAN  ,仍旧是脏选举哦,PREFERRED只会选择AR的第一个为Leader。
  • 稍等片刻,等1004掉出ISR列表之后,再重启1004这台机器。
  • 1004重启之后,开始向Leader同步数据,因为是新的磁盘,还没有任何数据,会自动重建。

上面有关怎么修改节点,节点格式应该是什么样子的,具体详情请看 ISR伸缩机制






最新经典文章,欢迎关注公众号



---------------------

作者:大数据架构师
来源:weixin
原文:实战 | Kafka生产环境磁盘坏了怎么办?



没找到任何评论,期待你打破沉寂

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条