Kafka磁盘坏了怎么办?

当事人描述

问题整理

  1. Broker 1004 上面的一块磁盘坏掉了。

  2. 坏的透透的,也没有RAID,反正就是这块磁盘数据恢复不了了。

  3. 因为1004坏了,导致副本离线,如果副本刚好是Leader,则会触发Leader重选举。

  4. 然后刚好有一些分区中的ISR只有1004,这个时候1004副本下线,重选举的时候Leader选不出来,就变成了-1,这些分区此时为不可用状态,需要里面恢复。

  5. 如果直接停机1004更换磁盘重启,那么势必会造成数据全部丢失、

  6. 分区都是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呢?

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

  2. 手动修改ISR里面的数据

解决问题

解法一:

  1. 停止Broker-1004,换上新的磁盘

  2. 执行一次脏选举kafka-leader-election.sh --UNCLEAN  

  3. 执行完毕之后,会从之前的Follower副本里面选出一个作为Leader

  4. 稍等片刻,等1004掉出ISR列表之后,再重启1004这台机器。

  5. 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%的准确性。

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

  1. 停止Broker-1004,换上新的磁盘

  2. 从Broker中找到你想要这么做的分区,查看recovery-point-offset-checkpoint文件比较一下,找到最大LEO的副本,这里你可能会有很多个分区

  3. 修改zk中/brokers/topics/{Topic名称}/partitions/{分区号}/state节点,把ISR改成只剩下你想要设为leader的副本id。

  4. 因为Controller平时不会监听state节点,所以你还需要再创建一个/isr_change_notification/isr_change_序号节点,触发Controller的监听,让他能触发Controller更新内存,还有给brokers发送UpdateMetadata请求
    例如: /isr_change_notification/isr_change_0000000001

// 这个表示的是 Topic2的0号分区 有ISR的变更
{"version":1,"partitions":[{"topic":"Topic2","partition":0}]}


  1. 改了ISR之后,仍旧不会触发Leader选举,所以这个时候我们可以手动触发一下kafka-leader-election.sh --UNCLEAN  ,仍旧是脏选举哦,PREFERRED只会选择AR的第一个为Leader。

  2. 稍等片刻,等1004掉出ISR列表之后,再重启1004这台机器。

  3. 1004重启之后,开始向Leader同步数据,因为是新的磁盘,还没有任何数据,会自动重建。

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

最后再说一句:除非你非常清楚自己在做什么,否则不要这么干,吃力不讨好的事情。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值