写点什么

4 种 Kafka 网络中断和网络分区场景分析

  • 2022 年 7 月 08 日
  • 本文字数:3005 字

    阅读完需:约 10 分钟

4种Kafka网络中断和网络分区场景分析

本文分享自华为云社区《Kafka网络中断和网络分区场景分析》,作者: 中间件小哥。


以 Kafka 2.7.1 版本为例,依赖 zk 方式部署


3 个 broker 分布在 3 个 az,3 个 zk(和 broker 合部),单分区 3 副本


1.  单个 broker 节点和 leader 节点网络中断


网络中断前:



broker-1 和 broker-0(leader)间的网络中断后,单边中断,zk 可用(zk-1 为 leader,zk-0 和 zk-2 为 follower,zk-0 会不可用,但 zk 集群可用,过程中可能会引起原本连在 zk-0 上的 broker 节点会先和 zk 断开,再重新连接其他 zk 节点,进而引起 controller 切换、leader 选举等,此次分析暂不考虑这种情况),leader、isr、controller 都不变



az2 内的客户端无法生产消费(metadata 指明 leader 为 broker-0,而 az2 连不上 broker-0),az1/3 内的客户端可以生产消费,若 acks=-1,retries=1,则生产消息会失败,error_code=7(REQUEST_TIMED_OUT)(因为 broker-1 在 isr 中,但无法同步数据),且会发两次(因为 retries=1),broker-0 和 broker-2 中会各有两条重复的消息,而 broker-1 中没有;由于 broker-0 没有同步数据,因此会从 isr 中被剔除,controller 同步 metadata 和 leaderAndIsr,isr 更新为[2,0]



网络恢复后,数据同步,更新 isr

2.  单个 broker 节点和 controller 节点网络中断


broker 和 controller 断连,不影响生产消费,也不会出现数据不一致的情况



而当发生 leader 和 isr 变化时,controller 无法将 leader 和 isr 的变化更新给 broker,导致元数据不一致



broker-0 故障时,controller(broker-2)感知,并根据 replicas 选举新的 leader 为 broker-1,但因为和 broker-1 网络中断,无法同步给 broker-1,broker-1 缓存的 leader 依然是 broker-0,isr 为[1,2,0];当客户端进行生产消费时,如果从 broker-2 拿到 metadata,认为 leader 为 1,访问 broker-1 会返回 NOT_LEADER_OR_FOLLOWER;如果从 broker-1 拿到 metadata,认为 leader 为 0,访问 broker-0 失败,都会导致生产消费失败

3.  非 controller 节点所在 az 被隔离(分区)



zk-0 和 zk-1、zk-2 不通,少于半数,az1 内 zk 不可用,broker-0 无法访问 zk,不会发生控制器控制器选举,controller 还是在 broker-1


网络恢复后,broker-0 加入集群,并同步数据

3.1 三副本分区(replicas:[1,0,2]),原 leader 在 broker-1(或 broker-2)



az1 内:


broker-0 无法访问 zk,感知不到节点变化,metadata 不更新(leader:1,isr:[1,0,2]),依然认为自己是 follower,leader 在 1;az1 内的客户端无法生产消费


az2/3 内:


zk 可用,感知到 broker-0 下线,元数据更新,且不发生 leader 切换(isr:[1,0,2] -> [1,2],leader:1);az2 和 az3 内的客户端可正常生产消费

3.2 三副本 partition(replicas:[0,1,2]),原 leader 在 broker-0



az1 内:


zk-0 和 zk-1、zk-2 连接中断,少于一半,az1 内 zk 集群不可用,Broker-0 连不上 zk,无法感知节点变化,且无法更新 isr,metadata 不变,leader 和 isr 都不变;az1 内客户端可以继续向 broker-0 生产消费


az2/3 内:


zk-1 和 zk-2 连通,zk 可用,集群感知到 broker-0 下线,触发 leader 切换,broker-1 成为新的 leader(时间取决于 zookeeper.session.timeout.ms),并更新 isr;az2/3 内的客户端可以向 broker-1 生产消费


此时,该分区出现了双主现象,replica-0 和 replica-1 均为 leader,均可以进行生产消费


若两个隔离域内的客户端都生产了消息,就会出现数据不一致的情况


示例:(假设网络隔离前有两条消息,leaderEpoch=0)


网络隔离前:



az1 隔离后,分区双主,az1 内的客户端写入 3 条消息:c、d、e,az2/3 内的客户端写入 2 条消息:f、g:



这里 leaderEpoch 增加 2,是因为有两次增加 leaderEpoch 的操作:一次是 PartitionStateMachine 的 handleStateChanges to OnlinePartition 时的 leader 选举,一次是 ReplicationStateMachine 的 handleStateChanges to OfflineReplica 时的 removeReplicasFromIsr


网络恢复后:



由于 controller 在 broker-2,缓存和 zk 中的 leader 都是 broker-1,controller 会告知 broker-0 makerFollower,broker-0 随即 add fetcher,会先从 leader(broker-1)获取 leaderEpoch 对应的 endOffset(通过 OFFSET_FOR_LEADER_EPOCH),根据返回的结果进行 truncate,然后开始 FETCH 消息,并根据消息中的 leaderEpoch 进行 assign,以此和 leader 保持一致



待数据同步后,加入 isr,并更新 isr 为[1,2,0]。之后在触发 preferredLeaderElection 时,broker-0 再次成为 leader,并增加 leaderEpoch 为 3


在网络隔离时,若 az1 内的客户端 acks=-1,retries=3,会发现生产消息失败,而数据目录中有消息,且为生产消息数的 4 倍(每条消息重复 4 次)



有前面所述可知,网络恢复后,offset2-13 的消息会被覆盖,但因为这些消息在生产时,acks=-1,给客户端返回的是生产失败的,因此也不算消息丢失


因此,考虑此种情况,建议客户端 acks=-1

4.  Controller 节点所在 az 被隔离(分区)

4.1 Leader 节点未被隔离



网络中断后,az3 的 zk 不可用,broker-2(原 controller)从 zk 集群断开,broker-0 和 broker-1 重新竞选 controller



最终 broker-0 选举为 controller,而 broker-2 也认为自己是 controller,出现 controller 双主,同时因连不上 zk,metadata 无法更新,az3 内的客户端无法生产消费,az1/2 内的客户端可以正常生产消费



故障恢复后,broker-2 感知到 zk 连接状态发生变化,会先 resign,再尝试竞选 controller,发现 broker-0 已经是 controller 了,放弃竞选 controller,同时,broker-0 会感知到 broker-2 上线,会同步 LeaderAndIsr 和 metadata 到 broker-2,并在 broker-2 同步数据后加入 isr


4.2 Leader 节点和 controller 为同一节点,一起被隔离


隔离前,controller 和 leader 都在 broker-0:



隔离后,az1 网络隔离,zk 不可用,broker-2 竞选为 controller,出现 controller 双主,同时 replica-2 成为 leader,分区也出现双主



此时的场景和 3.2 类似,此时生产消息,可能出现数据不一致



网络恢复后的情况,也和 3.2 类似,broker-2 为 controller 和 leader,broker-0 根据 leaderEpoch 进行 truncate,从 broker-2 同步数据



加入 isr,然后通过 preferredLeaderElection 再次成为 leader,leaderEpoch 加 1

5.  补充:故障场景引起数据不一致

5.1 数据同步瞬间故障


初始时,broker-0 为 leader,broker-1 为 follower,各有两条消息 a、b:



leader 写入一条消息 c,还没来得及同步到 follower,两个 broker 都故障了(如下电):



之后 broker-1 先启动,成为 leader(0 和 1 都在 isr 中,无论 unclean.leader.election.enable 是否为 true,都能升主),并递增 leaderEpoch:



然后 broker-0 启动,此时为 follower,通过 OFFSET_FOR_LEADER_EPOCH 从 broker-1 获取 leaderEpoch=0 的 endOffset



broker-0 根据 leader epoch endOffset 进行 truncate:



之后正常生产消息和副本同步:



该过程,如果 acks=-1,则生产消息 c 时,返回客户端的是生产失败,不算消息丢失;如果 acks=0 或 1,则消息 c 丢失

5.2 unclean.leader.election.enable=true 引起的数据丢失


还是这个例子,broker-0 为 leader,broker-1 为 follower,各有两条消息 a、b,此时 broker-1 宕机,isr=[0]



在 broker-1 故障期间,生产消息 c,因为 broker-1 已经不在 isr 中了,所以即使 acks=-1,也能生产成功



然后 broker-0 也宕机,leader=-1,isr=[0]



此时 broker-1 先拉起,若 unclean.leader.election.enable=true,那么即使 broker-1 不在 isr 中,因为 broker-1 是唯一活着的节点,因此 broker-1 会选举为 leader,并更新 leaderEpoch 为 2



这时,broker-0 再拉起,会先通过 OFFSET_FOR_LEADER_EPOCH,从 broker-1 获取 epoch 信息,并进行数据截断



再进行生产消息和副本同步



消息 c 丢失


点击关注,第一时间了解华为云新鲜技术~

发布于: 刚刚阅读数: 4
用户头像

提供全面深入的云计算技术干货 2020.07.14 加入

华为云开发者社区,提供全面深入的云计算前景分析、丰富的技术干货、程序样例,分享华为云前沿资讯动态,方便开发者快速成长与发展,欢迎提问、互动,多方位了解云计算! 传送门:https://bbs.huaweicloud.com/

评论

发布
暂无评论
4种Kafka网络中断和网络分区场景分析_后端_华为云开发者联盟_InfoQ写作社区