投稿:新炬網絡浙江大數據團隊
Kafka是一種快速、可擴展的,設計內在就是分布式的、分區的和可復制的提交日志服務。作為一種高吞吐量的分布式發布訂閱消息系統,Kafka被廣泛的應用于海量日志的收集、存儲。網上有大量Kafka架構、原理介紹的文章,本文不再重復贅述,重點談談Consumer Offset默認保存機制。
Topic作為一類消息的邏輯集合,Kafka集群為其維護了一個分區的日志,其結構如圖:
Topic每個分區是一個有序的、信息不斷追加的序列。分區中的每個消息都分配了一個連續的ID號,稱為偏移量(offset),用于唯一標識每個消息在分區中的位置。消費者根據自身保存的offset值確定各分區消費的位置。在0.8版本之前,Kafka一直將consumer的 offset信息記錄在ZooKeeper中。
Kafka的ZooKeeper存儲架構圖
如圖,在offsets的子節點中保存了不同的topic的offset 信息。Consumer在消費topic中的信息時需要不斷的更新ZooKeeper中的offset信息。
眾所周知,由于ZooKeeper并不適合大批量的頻繁寫入操作,從0.8.2版本開始Kafka開始支持將consumer的位移信息保存在Kafka內部的topic中(從0.9.0版本開始默認將offset存儲到系統topic中),雖然此舉解決了ZooKeeper頻繁寫入的性能瓶頸,但卻引入了新的問題。
以下是一個真實的案例:
磁盤使用率異常
某日Kafka集群的pc-xxx01主機的文件系統使用率超過80%,觸發告警。通過分析發現,topic __consumer_offset 相關log占用大量的磁盤空間。
圖1
圖2
如圖1、2所示,pc-xxx01主機data3目錄的磁盤使用率超過85%,其中__consumer_offset對應的24號分區的日志占用了952G,占總使用量的41%。
__consumer_offset的作用
圖3
如圖3所示,通過消費__consumer_offsets 分區24的數據可以發現,該topic保存的消息格式為[consumer group,topic name,partition]::[offsetmetadata[offset value,nometadata],committime value,expiratintime value],即一條消息包含消費組、topic、分區、offset值、提交時間、過期時間等信息。此topic正是kafka用來保存consumer offset的系統topic(根據實驗驗證該topic的消息以consumer group為key進行hash,相同consumer group的offset信息會被插入同一個partition)。
__consumer_offsets數據產生的頻率
Consumer消費消息之后會向offset manager 發送offsetCommitrequest請求,offset manager 負責將對應的consumer group、topic、partition、offset等信息插入__consumer_offsets topic。系統默認每60s為consumer提交一次offsetcommit請求(由auto.commit.interval.ms, auto.commit.enable兩個參數決定)。應用可以采用同步commit的方式進行數據消費(即consumer每處理一條消息觸發一次commit操作),這可能導致頻繁發送offsetCommitrequest請求的現象發生。
__consumer_offsets 數據保留策略
圖4
如圖4所示,當前__consumer_offsets 24號分區保留了16年10月到現在的所有消息日志,總量達到952G。
當前__consumer_offsets 的清理策略為compact,日志保留周期為24小時,但是系統默認的log.cleaner.enable為false,導致kafka不會對超過保留周期的數據進行壓縮處理,topic保留了系統上線以來的所有歷史數據。
不合理的同步提交方式
通過前期分析發現,__consumer_offsets 數據量暴增的24分區的數據主要來自于對log_xxx_plat_xx這個topic的消費組。通過獲取應用相關代碼分析發現,該topic相關consumer 采用了同步commit方式進行數據消費。
以上是官方文檔給出了consumer同步commit消費信息的兩種示例代碼。第一種方式,只要消費一條消息,就會產生一條commit記錄,數據量龐大;第二種方式,對同步commit做了精細化處理,每次批量數據消費,只會對被消費topic各分區中最后一條消息進行commit。如果一個topic包含10個分區,每次消費單個分區需要處理10條消息,采用第一種方式將產生100條commit記錄,而第二中方式只會產生10條commit記錄,差距巨大。經開發確認,相關應用正是采用了第一種方式進行同步commit。
系統topic分區大小異常的原因
通過以上分析,當前__connsumer_offsets部分分區數據量異常的問題是由于以下兩方面原因共同造成:
- __connsumer_offsets默認清理策略設置不當,導致過期歷史數據無法正常清理。
- 部分應用消費方式不當,導致產生大量commit信息。
針對該問題,我們后續優化策略如下,取得了不錯的成效。
- 要求應用優化代碼,減少commit信息的產生,應用進行代碼改造之后commit信息日增加量由原先的37G減少到1.5G。
- 調整topic 清理策略,將系統log.cleaner.enable設置為true,重起broker節點觸發日志清理。
優化之后__consumer_offsets 數據量由原先的900G下降到2G。
文章來自微信公眾號:DBAplus社群
本文鏈接:http://www.thecarconnectin.com/15123.html
網友評論comments