Kafka重複消費和丟失資料研究

Zollty發表於2016-12-31


Kafka重複消費原因

底層根本原因:已經消費了資料,但是offset沒提交。

原因1:強行kill執行緒,導致消費後的資料,offset沒有提交。

原因2:設定offset為自動提交,關閉kafka時,如果在close之前,呼叫 consumer.unsubscribe() 則有可能部分offset沒提交,下次重啟會重複消費。例如:

try {

consumer.unsubscribe();

} catch (Exception e) {

}

try {

consumer.close();

} catch (Exception e) {

}

上面程式碼會導致部分offset沒提交,下次啟動時會重複消費。


Kafka Consumer丟失資料原因

猜測:設定offset為自動定時提交,當offset被自動定時提交時,資料還在記憶體中未處理,此時剛好把執行緒kill掉,那麼offset已經提交,但是資料未處理,導致這部分記憶體中的資料丟失。



 

記錄offset和恢復offset的方案

 

理論上記錄offset,下一個group consumer可以接著記錄的offset位置繼續消費。

offset記錄方案:

每次消費時更新每個topic+partition位置的offset在記憶體中,

Map<key, value>,key=topic+'-'+partition,value=offset

當呼叫關閉consumer執行緒時,把上面Map的offset資料記錄到 檔案中*(分散式叢集可能要記錄到redis中)。

 

下一次啟動consumer,需要讀取上一次的offset資訊,方法是 以當前的topic+partition為key,從上次的Map中去尋找offset。

然後使用consumer.seek()方法指定到上次的offset位置。

 

說明:

1、該方案針對單臺伺服器比較簡單,直接把offset記錄到本地檔案中即可,但是對於多臺伺服器叢集,offset也要記錄到同一個地方,並且需要做去重處理。

      如果線上程式是由多臺伺服器組成的叢集,是否可以用一臺伺服器來支撐?應該可以,只是消費慢一點,沒多大影響。


2、如何保證接著offset消費的資料正確性

為了確保consumer消費的資料一定是接著上一次consumer消費的資料,

consumer消費時,記錄第一次取出的資料,將其offset和上次consumer最後消費的offset進行對比,如果相同則繼續消費。如果不同,則停止消費,檢查原因。






相關文章