kafka一直重複消費數據

告警數量在一次激增後,kafka消費數據異常,一直在不停的重複消費告警數據。

 

經排查爲位移自動提交導致:

自動提交

這種方式讓消費者來管理位移,應用本身不需要顯式操作。當我們將enable.auto.commit設置爲true,那麼消費者會在poll方法調用後每隔5秒(由auto.commit.interval.ms指定)提交一次位移。和很多其他操作一樣,自動提交也是由poll()方法來驅動的;在調用poll()時,消費者判斷是否到達提交時間,如果是則提交上一次poll返回的最大位移。

需要注意到,這種方式可能會導致消息重複消費。

假如,某個消費者poll消息後,應用正在處理消息,在3秒後Kafka進行了重平衡,那麼由於沒有更新位移導致重平衡後這部分消息重複消費。

 

poll(10): 即在10ms中內拉去的數據返回到消費者端。

//10ms可以讀取到大量數據,無法在auto.commit.interval.ms配置的時間內完成處理。

關閉自動提交,採用主動提交後恢復正常,建議採用主動提交方式,可以最大程度避免數據重複消費。

 

提交當前位移

爲了減少消息重複消費或者避免消息丟失,很多應用選擇自己主動提交位移。設置auto.commit.offset爲false,那麼應用需要自己通過調用commitSync()來主動提交位移,該方法會提交poll返回的最後位移。

爲了避免消息丟失,我們應當在完成業務邏輯後才提交位移。而如果在處理消息時發生了重平衡,那麼只有當前poll的消息會重複消費。下面是一個自動提交的代碼樣例:


 

while (true) {
    ConsumerRecords<String, String> records = consumer.poll(100);
    for (ConsumerRecord<String, String> record : records)
    {
        System.out.printf("topic = %s, partition = %s, offset = %d, customer = %s, country = %s\n", record.topic(), record.partition(), record.offset(), record.key(), record.value());
    }
    
    try {
        consumer.commitSync();
    } catch (CommitFailedException e) {
        log.error("commit failed", e)
    }
}

上面代碼poll消息,並進行簡單的打印(在實際中有更多的處理),最後完成處理後進行了位移提交。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章