The following article is from 石臻臻的杂货铺 Author 彦祖
CSDN博客之星Top5、Kafka Contributor、LogiKM PMC、华为云MVP。进滴滴技术交流群, 不同技术专家轮流值班, 本号分享Java/大数据/中间件等领域干货和视频
生产环境的事故,时间就是金钱(请这位同学一会给我结个账)。来,咱们就一起来帮他看一看。
当事人的问题描述
问题整理
“彦祖,应该怎么办才能将损失降到最低啊?”
磁盘不是 RAID 不能容错,想恢复数据是不大可能了。这里我们不考虑其他一些方式恢复磁盘。
一般来说,Kafka 的多副本就是用来应对这种情况的,Follower 副本用来备份容错,这里分区都是 3 个副本。既然1004中的副本丢失了,没有关系,还有其他副本的数据。
但是坏就坏在,有一些分区的 Follower 不在 ISR 里面。ISR 表示的是同步副本,跟 Leader 保持较高的同步。如果配合 ack=all 可以达到最高的可靠性。
ISR 里面只有 1004,如果贸然停机 1004,换上新盘再重启会造成什么情况?
会造成数据全部丢失
当 1004 再次重启的时候,它会再次当选为 Leader。那么,其他的 Follower 副本就会去同步 Leader。如果发现自己的数据跟 Leader 不一致,就会截断自己的数据。这个时候 Leader 没有数据,Follower 截断之后那就全没了。
那我让其他副本当选为 Leader 是不是就可以避免上面的问题了?
嗯,没错。为了避免上面的问题,我们只能先让其他的副本当选 Leader 了。
那么,如何选举其他副本为 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% 的准确性。
如果你说一定要这样做(可以但没有必要),那我也给你提供这么一个思路(非源码层面的)。
// 这个表示的是 Topic2的0号分区 有ISR的变更{"version":1,"partitions":[{"topic":"Topic2","partition":0}]}
上面有关怎么修改节点,节点格式应该是什么样子的,具体详情可以去了解 ISR 伸缩机制。
最后再说一句,除非你非常清楚自己在做什么,否则不要这么干。吃力不讨好的事情。
- EOF -
看完本文有收获?请转发分享给更多人
关注「ImportNew」,提升Java技能
点赞和在看就是最大的支持❤️