天天看點

Apache Kafka源碼分析 – Log Management

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