Kafka無法消費?!我的分布式消息服務Kafka卻穩如泰山!
問題現象:消費請求卡死在查找Coordinator
Coordinator為何物?Coordinator用於管理Consumer Group中各個成員,負責消費offset位移管理和Consumer Rebalance。Consumer在消費時必須先確認Consumer Group對應的Coordinator,隨後才能join Group,獲取對應的topic partition進行消費。
那如何確定Consumer Group的Coordinator呢?分兩步走:
1、一個Consumer Group對應一個consumers_offsets的分區,首先先計算Consumer Group對應的__consumers_offsets的分區,計算公式如下:
2、1中計算的該partition的leader所在的broker就是被選定的Coordinator。
定位過程
Coordinator節點找到了,現在看看Coordinator是否有問題:
不出所料,Coordinator對應分區Leader為-1,消費端程序會一直等待,直到Leader選出來為止,這就直接導致了消費卡死。
- 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發生變化,自身清退 - 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切換了,它也不感知。 - 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.
So,推薦大家可以關註一下菊廠分布式消息服務Kafka(DMS),經過電信級驗證,已經完美解決了這些問題
Kafka無法消費?!我的分布式消息服務Kafka卻穩如泰山!