consumer初始化時會從broker取commit offset作為初始fetch offset來取消息,之后會繼續(xù)在fetch offset上按順序正確的往后取消息轿秧。所以正常的運行只依靠fetch offset就足夠了鸳劳,而且fetch offset在初始化之后就不需要用戶理會,由consumer自行管理維護染苛。 consumer的commit作為松散的支線可以在任意時間點執(zhí)行,commit的意義在于盡可能及時的把消費處理的結果刷回broker去几缭,以備consumer重啟初始化或通過adminClient讀取使用,所以習慣上成功消費一條就commit一次沃呢。一般來說commit offset會落后fetch offset一些年栓,另外即使一次commit失敗了也沒關系,只要后序commit成功就能掩蓋薄霜。
consumer的commit offset保存在broker集群的有50個partition的內(nèi)部topic里某抓,保存時間 offsets.retention.minutes (1440 minutes = 1 day) 的意思是說超過這個時間沒有再次commit就刪除該consumer的commit offfset竿刁,意義在于刪除長期離線的consumer的commit信息。如果consumer從broker取commit時搪缨,還沒有提交過offset或是已經(jīng)被刪除食拜,就返回0。
broker里的topic消息log只會保留 log.retention.hours (168 hours = 7 days) 副编,時間點以前的消息就會被截斷刪除负甸。而consumer的配置 auto.offset.reset(earliest | latest) 當consumer提供的fetch offset超出broker留存的消息log范圍時,把fetch offset重置到broker留存消息的最小位或最大位痹届。
場景描述:
因為commit offset的保存時間offsets.retention.minutes只有1天呻待,而消息log的保存時間log.retention.hours有7天。
如果consumer是手動commit队腐,當長時間沒有新消息可以消費蚕捉,也就長時間沒有commit,造成commit offset被broker刪除柴淘。之后一旦consumer重啟迫淹,初始化時發(fā)現(xiàn)commit offset已經(jīng)被刪除,取到了0去fetch为严,必定會超出broker的留存消息范圍敛熬,觸發(fā)consumer的reset。如果reset=earliest 就會從留存的7天內(nèi)的最小位消息開始消費第股,造成大量的重復消費应民。如果reset=latest 就會從最新消息開始消費,造成會丟失重啟期間的消息夕吻。
結論:
不能在還有數(shù)據(jù)的時候诲锹,失去對數(shù)據(jù)消費的commit信息。不然會在consumer重啟時把consumer reset到broker現(xiàn)有數(shù)據(jù)的最小位或最大位開始消費涉馅,造成數(shù)據(jù)重復或丟失归园。
反過來如果有commit信息,但數(shù)據(jù)已經(jīng)被刪除了控漠,有兩種情況
(1)說明consumer長期離線蔓倍,這樣的數(shù)據(jù)消費缺失是合理的悬钳,根據(jù)reset配置從當前現(xiàn)有數(shù)據(jù)的最小位或最大位開始消費盐捷。
(2)數(shù)據(jù)全部被消費過, 只是正常的過期刪除默勾,所以這并沒有任何問題碉渡,也不會發(fā)生reset。
正常情況下母剥,commit offset保存時間可以配置成消息log保存時間的2倍滞诺,如果log.retention.hours 仍然為 7 days形导,那 offsets.retention.minutes 可以配置成 14 days。習慣上把消息log配置保存 3 days习霹,offsets配置保存 6 days朵耕。