国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

kafka的log存儲是怎么設計的?

2019-11-08 20:39:22
字體:
來源:轉載
供稿:網友

Kafka中的Message是以topic為基本單位組織的,不同的topic之間是相互獨立的。每個topic又可以分成幾個不同的partition(每個topic有幾個partition是在創建topic時指定的),每個partition存儲一部分Message。借用官方的一張圖,可以直觀地看到topic和partition的關系。Anatomy of a Topic

partition是以文件的形式存儲在文件系統中,比如,創建了一個名為page_visits的topic,其有5個partition,那么在Kafka的數據目錄中(由配置文件中的log.dirs指定的)中就有這樣5個目錄: page_visits-0, page_visits-1,page_visits-2,page_visits-3,page_visits-4,其命名規則為<topic_name>-<partition_id>,里面存儲的分別就是這5個partition的數據。

接下來,本文將分析partition目錄中的文件的存儲格式和相關的代碼所在的位置。

Partition的數據文件

Partition中的每條Message由offset來表示它在這個partition中的偏移量,這個offset不是該Message在partition數據文件中的實際存儲位置,而是邏輯上一個值,它唯一確定了partition中的一條Message。因此,可以認為offset是partition中Message的id。partition中的每條Message包含了以下三個屬性:

offsetMessageSizedata

其中offset為long型,MessageSize為int32,表示data有多大,data為message的具體內容。它的格式和Kafka通訊協議中介紹的MessageSet格式是一致。

Partition的數據文件則包含了若干條上述格式的Message,按offset由小到大排列在一起。它的實現類為FileMessageSet,類圖如下:FileMessageSet類圖它的主要方法如下:

append: 把給定的ByteBufferMessageSet中的Message寫入到這個數據文件中。searchFor: 從指定的startingPosition開始搜索找到第一個Message其offset是大于或者等于指定的offset,并返回其在文件中的位置Position。它的實現方式是從startingPosition開始讀取12個字節,分別是當前MessageSet的offset和size。如果當前offset小于指定的offset,那么將position向后移動LogOverHead+MessageSize(其中LogOverHead為offset+messagesize,為12個字節)。read:準確名字應該是slice,它截取其中一部分返回一個新的FileMessageSet。它不保證截取的位置數據的完整性。sizeInBytes: 表示這個FileMessageSet占有了多少字節的空間。truncateTo: 把這個文件截斷,這個方法不保證截斷位置的Message的完整性。readInto: 從指定的相對位置開始把文件的內容讀取到對應的ByteBuffer中。

我們來思考一下,如果一個partition只有一個數據文件會怎么樣?

新數據是添加在文件末尾(調用FileMessageSet的append方法),不論文件數據文件有多大,這個操作永遠都是O(1)的。查找某個offset的Message(調用FileMessageSet的searchFor方法)是順序查找的。因此,如果數據文件很大的話,查找的效率就低。

那Kafka是如何解決查找效率的的問題呢?有兩大法寶:1) 分段 2) 索引。

數據文件的分段

Kafka解決查詢效率的手段之一是將數據文件分段,比如有100條Message,它們的offset是從0到99。假設將數據文件分成5段,第一段為0-19,第二段為20-39,以此類推,每段放在一個單獨的數據文件里面,數據文件以該段中最小的offset命名。這樣在查找指定offset的Message的時候,用二分查找就可以定位到該Message在哪個段中。

為數據文件建索引

數據文件分段使得可以在一個較小的數據文件中查找對應offset的Message了,但是這依然需要順序掃描才能找到對應offset的Message。為了進一步提高查找的效率,Kafka為每個分段后的數據文件建立了索引文件,文件名與數據文件的名字是一樣的,只是文件擴展名為.index。索引文件中包含若干個索引條目,每個條目表示數據文件中一條Message的索引。索引包含兩個部分(均為4個字節的數字),分別為相對offset和position。

相對offset:因為數據文件分段以后,每個數據文件的起始offset不為0,相對offset表示這條Message相對于其所屬數據文件中最小的offset的大小。舉例,分段后的一個數據文件的offset是從20開始,那么offset為25的Message在index文件中的相對offset就是25-20 = 5。存儲相對offset可以減小索引文件占用的空間。position,表示該條Message在數據文件中的絕對位置。只要打開文件并移動文件指針到這個position就可以讀取對應的Message了。

index文件中并沒有為數據文件中的每條Message建立索引,而是采用了稀疏存儲的方式,每隔一定字節的數據建立一條索引。這樣避免了索引文件占用過多的空間,從而可以將索引文件保留在內存中。但缺點是沒有建立索引的Message也不能一次定位到其在數據文件的位置,從而需要做一次順序掃描,但是這次順序掃描的范圍就很小了。

在Kafka中,索引文件的實現類為OffsetIndex,它的類圖如下:OffsetIndex類圖

主要的方法有:

append方法,添加一對offset和position到index文件中,這里的offset將會被轉成相對的offset。lookup, 用二分查找的方式去查找小于或等于給定offset的最大的那個offset小結:kafka log 可以說是順序讀寫的,對于這種順序結構的消息,讀的方法很多系統設計是類似的,比如淘寶的tt,log存儲在hbase中,將時間戳作為offset,時間戳寫進hbase的rowkey里,那么hbase的表本身就是按行分region的,因此kafka的log segment其實你可以理解成hbase的region,同時,因為hbase有更復雜的索引機制,因此tt不需要自行設計讀取的方法,而kafka這里,有了segment之后,一定程度上提供了查詢的效率,但是還不夠,還要做索引,否則只能全部加載到內存再順序查找,但是如果每條消息都做索引,索引文件又太大了,怎么辦,只能折中,做稀疏索引,即分段做索引,相當于又給segment做了segment。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 柏乡县| 宜宾市| 玉溪市| 宁乡县| 韶关市| 阳西县| 宁南县| 华亭县| 长宁县| 修文县| 营山县| 万宁市| 咸丰县| 商河县| 武夷山市| 桐城市| 平塘县| 平南县| 炎陵县| 博乐市| 和平区| 南岸区| 沁水县| 治县。| 安化县| 会泽县| 鹰潭市| 元氏县| 上饶县| 惠州市| 镇雄县| 绥阳县| 碌曲县| 信阳市| 东台市| 开远市| 澳门| 报价| 镇雄县| 高陵县| 大姚县|