Kafka沒法消費!?到底是bug的「淪陷」仍是配置的「扭曲」?

在一個月黑風高的夜晚,忽然收到現網生產環境Kafka消息積壓的告警,夢中驚醒啊,立刻起來排查日誌。html

 

問題現象網絡

消費請求卡死在查找Coordinator分佈式

 

Coordinator爲什麼物?Coordinator用於管理Consumer Group中各個成員,負責消費offset位移管理和Consumer Rebalance。Consumer在消費時必須先確認Consumer Group對應的Coordinator,隨後才能join Group,獲取對應的topic partition進行消費。3d

 

那如何肯定Consumer Group的Coordinator呢?分兩步走:日誌

一、一個Consumer Group對應一個__consumers_offsets的分區,首先先計算Consumer Group對應的__consumers_offsets的分區,計算公式以下:htm

__consumers_offsets partition# = Math.abs(groupId.hashCode() % groupMetadataTopicPartitionCount,其中groupMetadataTopicPartitionCount由offsets.topic.num.partitions指定。blog

二、1中計算的該partition的leader所在的broker就是被選定的Coordinator。事件

 

定位過程內存

Coordinator節點找到了,如今看看Coordinator是否有問題:get

 

不出所料,Coordinator對應分區Leader爲-1,消費端程序會一直等待,直到Leader選出來爲止,這就直接致使了消費卡死。

爲啥Leader沒法選舉?Leader選舉是由Controller負責的。Controller節點負責管理整個集羣中分區和副本的狀態,好比partition的Leader選舉,topic建立,副本分配,partition和replica擴容等。如今咱們看看Controller的日誌:

1.6月10日15:48:30,006 秒Broker 1成爲controller

此時感知的節點爲1和2,節點3 在zk讀不出來:

31秒847的時候把__consumer_offsets的分區3的Leader選爲1,ISR爲[1,2],leader_epoch爲14:

再過1秒後才感知到Controller發生變化,自身清退

 

2.Broker 2在其後幾百毫秒後(15:48:30,936)也成爲Controller

可是Broker2 是感知到Broker 3節點是活的,日誌以下:

注意這個時間點,Broker1還沒在zk把__consumer_offsets的分區3 的Leader從節點3改成1,這樣Broker 2還認爲Broker 3是Leader,而且Broker 3在它認爲是活的,因此不須要從新選舉Leader。這樣一直保持了至關長的時間,即便Broker 1已經把這個分區的Leader切換了,它也不感知。

 

3.Broker 2在12號的21:43:19又感知Broker 1網絡中斷,並處理節點失敗事件:

 

由於Broker 2內存中認爲__consumer_offsets分區3的Leader是broker 3,因此不會觸發分區3的Leader切換。

Broker 2可是在處理失敗的節點Broker 1時,會把副本從ISR列表中去掉,去掉前會讀一次zk,代碼以下:

可是發現zk中分區3的Leader已經變爲1,ISR列表爲[1,2],當要去掉的節點1就是Leader的時候,Leader就會變爲-1, ISR只有[2],從日誌也能夠看到:

這樣分區3 的Leader一直爲-1,直到有新的事件觸發節點2從新選舉才能恢復(例如重啓某個節點)。

 

根因總結

出現網絡異常後,因爲新老controller之間感知的可用節點不一樣,致使新controller對某個分區的Leader在內存中的信息與zk記錄元數據的信息不一致,致使controller選舉流程出現錯誤,選不出Leader。 須要有新的選舉事件才能觸發Leader選出來,例如重啓。

 

問題總結

這是一個典型的因爲網絡異常致使腦裂,進而出現了多個Controller,華爲雲分佈式消息服務(DMS)Kafka通過電信級的可靠性驗證,已經完美解決了這些問題,點擊這裏瞭解更多~

相關文章
相關標籤/搜索