logmanager
logmanager會管理broker上所有的logs(在一個log目錄下),一個topic的一個partition對應于一個log(一個log子目錄)
首先loadlogs會加載每個partition所對應的log對象, 然後提供createlog,getlog,deletelog之類的管理接口
并且會建立些背景線程來進行,cleanup,flush,checkpoint生成之類的工作
log
log隻是對于logsegments的封裝,包含loadsegments,append(到active segment),read(需要定位到相應的segment)
logsegment
segment是個邏輯概念,為了防止log檔案過大, 将log分成許多的logsegments
segment又分為兩部分,messageset檔案和index檔案,分别命名為[base_offset].log和[base_offset].index
base_offset就是該segment的起始offset,比前一個segment裡面的offset都要大
segment提供對于messageset的讀寫接口
寫,需要間隔的更新index檔案,應該為了盡量減小index的size,是以隻是當寫入資料大于indexintervalbytes時,才增加一條索引
讀,由于user傳入的是邏輯offest,需要先轉化為實體位址才能從檔案中讀到資料,如何轉化參考下面
同時index檔案是可以根據messageset檔案重新rebuild的
filemessageset
segment中實際存放log message的檔案,通過filechannel可以讀寫檔案
offsetindex
segment的index檔案, 這是0.8後加上的,之前message直接使用實體offset辨別
新版本中還是改成了使用邏輯offset,讓實體位址對使用者透明, 這樣就需要一個index來比對邏輯offset和實體位址
注釋裡面說,
index是sparse的,不保證每個message在index都有索引的entry
index由entry組成,每個entry為8-byte,邏輯offset4-byte,實體位址4-byte
并且邏輯offset是基于base offset的相對offset,否則無法保證隻使用4-byte
具體看看如何從邏輯offset轉化為實體位址的?
0.8中增加了邏輯offset,那麼就需要做邏輯offset和實體位址間的轉化
簡單的方法,直接用hashmap,cache所有offset,問題就是這樣空間耗費比較大
是以kafka的方式,是分段索引,用offset通過二分查找中index中找出段的起始位址,然後再去file裡面周遊找出精确的位址, 時間換空間的設計
1. logsegment.translateoffset
首先是從index檔案中找到近似的實體位址
前面說了,index中從效率考慮并不會為每個offset建立索引entry,隻會分段建立offset索引, 是以從index中直接可以找到精确實體位址的機率不大,但是可以找到最接近的那個實體位址
如果你覺得index的粒度比較粗,可以直接給出開始查找的startingfileposition
是以精确的實體位址需要到messageset檔案裡面去繼續找
2. filemessageset.searchfor
在messageset中,message的構成是,overhead(messagesize+offset)和message
而searchfor的邏輯是從startingposition開始, 逐條周遊各個message,并從overhead中取出offset進行比較,直到找到target offset為止
本文章摘自部落格園,原文釋出日期:2014-02-18