Jafka原始碼分析——LogManager

來源:互聯網
上載者:User

標籤:kafka   jfaka   訊息中介軟體   原始碼   



在Kafka中,LogManager負責管理broker上所有的Log(每一個topic-partition為一個Log)。通過閱讀原始碼可知其具體完成的功能如下:

1. 按照預設規則對訊息佇列進行清理。

2. 按照預設規則對訊息佇列進行持久化(flush操作)。

3. 串連ZooKeeper進行broker、topic、partition相關的ZooKeeper操作。

4. 管理broker上所有的Log。

下面一一對這些功能的實現進行詳細的解析。

一、對於Log的管理

LogManager包含成員變數logs。logs的key是topic,value是Pool<Integer,Log>(該value又是一個Map,主鍵是partition,value是該partition所對應的Log)。因此LogManager通過logs儲存該broker上所有的訊息佇列。

private final Pool<String, Pool<Integer, Log>> logs = new Pool<String, Pool<Integer, Log>>();

LogManager在初始化之後,需要根據設定檔配置的訊息佇列根目錄進行遍曆。通過遍曆,尋找並產生Log。該遍曆的具體實現在方法load中:

① 擷取訊息佇列根目錄下的所有檔案

② 對於根目錄下的每一個檔案進行如下操作

 1.如果是目錄,則有可能是一個Log,否則不是並忽略

 2.對於通過1的目錄分析其檔案名稱,目錄的檔案名稱由兩部分組成:topic-partition

 3.對於通過2的目錄,用目錄、解析出的topic、解析出的partition產生Log

 4.將3產生的Log放入logs日誌池

 5.最後,判斷目錄解析的partition與設定檔中配置的partition的大小,如果設定檔較小,則更新配置


二、訊息佇列清理

訊息佇列的清理由Scheduler周期性的調用,具體的調用在load函數中,主要的刪除實現在cleanLogs函數中。訊息佇列的清理分為兩種情況:一種是超過預設的時間則刪除,二是超過預設的大小則刪除,分別對應兩個函數cleanupExpiredSegments和cleanupSegmentsToMaintainSize。第一種情況比較簡單,因為每一個segment對應一個檔案,通過對比檔案的lastModifiedTime和系統的現在時間來確定其是否逾時,如果逾時則刪除。對於第二種情況,首先比較Log的大小與配置的大小。如果小於配置的大小則不刪除;如果大於了配置的大小,則計算超過配置大小的長度(定為差值);然後將小於該差值的segment刪除(這地方有點疑惑,這樣刪除會不會把一些最新的訊息佇列給刪除了)。

 if (this.scheduler != null) { this.scheduler.scheduleWithRate(new Runnable() {                public void run() {                    try {                        cleanupLogs();                    } catch (IOException e) {                        logger.error("cleanup log failed.", e);                    }                }            }, 60 * 1000, logCleanupIntervalMs);}


三、對於訊息佇列的持久化

對訊息佇列的flush操作同樣由單獨的線程來完成。該線程通過比較Log上一次的flush時間和當前的系統時間來確定是否需要flush,如果需要則持久化到檔案。注意,訊息的隊列的持久化在新增訊息的時候也會判斷,如果一個Log儲存的新增訊息的條數超過了預設值則進行flush操作。


在Kafka中,LogManager負責管理broker上所有的Log(每一個topic-partition為一個Log)。通過閱讀原始碼可知其具體完成的功能如下:

1. 按照預設規則對訊息佇列進行清理。

2. 按照預設規則對訊息佇列進行持久化(flush操作)。

3. 串連ZooKeeper進行broker、topic、partition相關的ZooKeeper操作。

4. 管理broker上所有的Log。

下面一一對這些功能的實現進行詳細的解析。

一、對於Log的管理

LogManager包含成員變數logs。logs的key是topic,value是Pool<Integer,Log>(該value又是一個Map,主鍵是partition,value是該partition所對應的Log)。因此LogManager通過logs儲存該broker上所有的訊息佇列。

private final Pool<String, Pool<Integer, Log>> logs = new Pool<String, Pool<Integer, Log>>();

LogManager在初始化之後,需要根據設定檔配置的訊息佇列根目錄進行遍曆。通過遍曆,尋找並產生Log。該遍曆的具體實現在方法load中:

① 擷取訊息佇列根目錄下的所有檔案

② 對於根目錄下的每一個檔案進行如下操作

 1.如果是目錄,則有可能是一個Log,否則不是並忽略

 2.對於通過1的目錄分析其檔案名稱,目錄的檔案名稱由兩部分組成:topic-partition

 3.對於通過2的目錄,用目錄、解析出的topic、解析出的partition產生Log

 4.將3產生的Log放入logs日誌池

 5.最後,判斷目錄解析的partition與設定檔中配置的partition的大小,如果設定檔較小,則更新配置


二、訊息佇列清理

訊息佇列的清理由Scheduler周期性的調用,具體的調用在load函數中,主要的刪除實現在cleanLogs函數中。訊息佇列的清理分為兩種情況:一種是超過預設的時間則刪除,二是超過預設的大小則刪除,分別對應兩個函數cleanupExpiredSegments和cleanupSegmentsToMaintainSize。第一種情況比較簡單,因為每一個segment對應一個檔案,通過對比檔案的lastModifiedTime和系統的現在時間來確定其是否逾時,如果逾時則刪除。對於第二種情況,首先比較Log的大小與配置的大小。如果小於配置的大小則不刪除;如果大於了配置的大小,則計算超過配置大小的長度(定為差值);然後將小於該差值的segment刪除(這地方有點疑惑,這樣刪除會不會把一些最新的訊息佇列給刪除了)。

 if (this.scheduler != null) { this.scheduler.scheduleWithRate(new Runnable() {                public void run() {                    try {                        cleanupLogs();                    } catch (IOException e) {                        logger.error("cleanup log failed.", e);                    }                }            }, 60 * 1000, logCleanupIntervalMs);}


三、對於訊息佇列的持久化

對訊息佇列的flush操作同樣由單獨的線程來完成。該線程通過比較Log上一次的flush時間和當前的系統時間來確定是否需要flush,如果需要則持久化到檔案。注意,訊息的隊列的持久化在新增訊息的時候也會判斷,如果一個Log儲存的新增訊息的條數超過了預設值則進行flush操作。


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.