天天看點

HDFS 細粒度鎖優化,FusionInsight MRS有妙招

摘要:華為雲FusionInsight MRS通過FGL對HDFS NameNode鎖機制進行優化,有效提升了NameNode的讀寫吞吐量,進而能夠支援更多資料,更多業務請求通路,進而更好的支撐政企客戶高效用數,業務洞見更準,價值兌現更快。

本文分享自華為雲社群《​​FusionInsight MRS HDFS 細粒度鎖優化實踐​​》,作者:pippo。

背景

HDFS依賴NameNode作為其中繼資料服務。NameNode将整個命名空間資訊儲存在記憶體中提供服務。讀取請求(getBlockLocations、listStatus、getFileInfo)等從記憶體中擷取資訊。寫請求(mkdir、create、addBlock)更新記憶體狀态,并将日志事務寫入到日志服務(QJM)。

HDFS NameNode的性能決定了整個Hadoop叢集的可擴充性。命名空間性能的改進對于進一步擴充Hadoop叢集至關重要。

Apache HDFS 整體架構如下:

HDFS 細粒度鎖優化,FusionInsight MRS有妙招

Apache HDFS 互動資訊如下:

HDFS 細粒度鎖優化,FusionInsight MRS有妙招

痛點

HDFS NameNode的寫操作的性能受全局命名空間系統鎖的限制。每個寫操作都會擷取鎖并保留鎖,直到該操作執行完成。這樣可以防止寫入操作的并發執行,即使它們是完全獨立的,例如命名空間中的對象不相交部分。

什麼是Fine Grained Locking(FGL)

FGL【細粒度鎖】的主要目的是通過在獨立命名空間分區上用多個并發鎖替換全局鎖,允許寫入操作的并發。

目前狀态

HDFS設計思路為一次寫,多次讀。讀操作使用共享鎖,寫操作使用獨占鎖。由于HDFS NameNode中繼資料被設計為單個記憶體空間中的命名空間樹,是以樹的任何級别的寫操作都會阻塞其它寫操作,直到目前寫操作完成。雖然寫是一次,但是當涉及大量并發讀/寫操作時,這就會影響整體性能。

在HDFS NameNode中,記憶體中的中繼資料有三種不同的資料結構:

  • INodeMap: inodeid -> INode
  • BlocksMap: blockid -> Blocks
  • DataNodeMap: datanodeId -> DataNodeInfo

INodeMap結構中包含inodeid到INode的映射,在整個Namespace目錄樹種存在兩種不同類型的INode資料結構:INodeDirectory和INodeFile。其中INodeDirectory辨別的是目錄樹中的目錄,INodeFile辨別的是目錄樹中的檔案。

BlocksMap結構中包含blockid到BlockInfo的映射。每一個INodeFile都會包含數量不同的Block,具體數量由檔案大小以及每個Block大小來決定,這些Block按照所在檔案的先後順序組成BlockInfo數組,BlockInfo維護的是Block的中繼資料;通過blockid可以快速定位Block。

DataNodeMap結果包含datanodeid到DataNodeInfo的映射。當叢集啟動過程中,通過機架感覺逐漸建立起整個叢集的機架拓撲結構,一般在NameNode的生命周期内不會發生大變化。

通過INodeMap和BlocksMap共同辨別存儲在HDFS中的每個檔案及其塊的資訊。随着檔案數量的增加,此資料結構大小也會随之增加,并對單個全局鎖的性能産生很大影響。下面我們采用簡單的檔案目錄樹結構來示範現有的單一全局鎖在檔案系統的缺點。

HDFS 細粒度鎖優化,FusionInsight MRS有妙招

HDFS NameNode 記憶體目錄樹結構

如上圖所示,/D11/D21/D31/F2 和 /D12/D24/D38/F16是不相交的檔案,即有不同的父節點和祖父節點。可以看到F2和F16是兩個獨立的檔案,對其中一個檔案的任何操作都不應該影響另一個檔案。

設計

如前所述,HDFS NameNode将檔案資訊和中繼資料結構在記憶體中儲存為一個目錄樹結構。當修改任意兩個獨立的檔案時,第二次操作需要等到第一次操作完成并釋放鎖。釋放鎖以後,隻有第二個操作擷取鎖後才能繼續修改檔案系統。類似的,後續操作也會阻塞,直到第二次操作釋放鎖。

在下面的例子中,我們考慮2個檔案并發寫入(建立、删除、追加。。。)操作。F2和F16是檔案系統下的2個獨立檔案(具有不同的父節點和祖父節點)。在将内容追加到F2時,F16也可以同時進行修改。但是由于整個目錄樹全局對象鎖,對F16的操作必須等對F2的操作完成後才能執行。

代替全局鎖,可以将鎖分布在一組名為“分區”的檔案中,每個分區都可以有自己的鎖。現在F2屬于分區-1,F16屬于分區-2。F2檔案操作可以通過擷取分區-1的鎖來進行修改,F16檔案操作可以通過擷取分區-2的鎖來進行修改。

和以前一樣,需要先擷取全局鎖,然後搜尋每個檔案屬于哪個分區。找到分區後,擷取分區鎖并釋放全局鎖。是以全局鎖并不會完全被删除。相反,通過減少全局鎖時間跨度,一旦釋放全局鎖,則其它寫操作可以擷取全局鎖并繼續擷取分區鎖來進行檔案操作。

HDFS 細粒度鎖優化,FusionInsight MRS有妙招

分區的數量如何決定?如果有效的定義分區進而獲得更高的吞吐量?

預設情況下,分區大小為65K,溢出系數為1.8。一旦分區達到溢出條件,将會建立新分區并加入到分區清單中。理想情況下,可以擁有等于NameNode可用CPU核數的分區數,過多的分區數量将會使得CPU過載,而過少的分區數量無法充分利用CPU。

實作

引入新的資料結構-PartitionedGSet,它儲存命名空間建立的所有分區資訊。PartitionEntry是一個分區的對象結構。LatchLock是新引入的鎖,用于控制兩級鎖--頂層鎖和子鎖。

PartitionedGSet

PartitionedGSet是一個兩級層次結構。第一層RangeMap定義了INode的範圍,并将它們映射到相應的分區中。分區構成了層次結構的第二級,每個分區存儲屬于指定範圍的INode資訊。為了根據鍵值查找INode,需要首先在RangeMap中找到對應鍵值的範圍,然後在對應的RangeSet,使用哈希值擷取到對應的INode。

HDFS NameNode 兩級層次結構

RangeGSet的容量有一定的門檻值。當達到門檻值後,将建立新的RangeGSet。空的或者未充分利用的RangeGSet由背景RangeMonitor守護程式來進行垃圾回收。

HDFS NameNode啟動時,根據鏡像中的INode數量計算合理的初始分區數。同時還需要考慮CPU核數,因為将分區數量提高到遠超CPU核數并不會增加系統的并行性。

  • 動态分區:分區的大小有限,可以像平衡樹一樣可以進行分裂和合并。
  • 單個分區:隻有一個分區,且隻有一個與之相對應的鎖,并且應和全局鎖類似。這适用于小型叢集或寫入負載比較輕的叢集。
  • 靜态分區:有一個固定的RangeMap,不添加或者合并現有分區。這适用于分區均勻增長的檔案系統。而且這将消除鎖定RangeMap的要求,允許并行使用鎖。

Latch Lock

RangeMap與RangeGSet分别有單獨的鎖。Latch Lock是一種鎖模式,其中首先擷取RangeMap的鎖,以查找與給定INode鍵對應的範圍,然後擷取與分區對應的RangeGSet的鎖,同時釋放RangeMap鎖。這樣針對任何其它範圍的下一個操作都可以開始并發執行。

在RangeMap上持有鎖類似于全局鎖。目錄删除、重命名、遞歸建立目錄等幾個操作可能需要鎖定多個RangeGSet。這要確定目前HDFS語義所要求的操作的原子性。例如,如果重命名将檔案從一個目錄移動到另一個目錄,則必須鎖定包含檔案、源和目标目錄的RangeMap,以便使重命名成為原子。此鎖定模式的一個理想優化是允許某些操作的Latch Lock與其他操作的全局鎖結合使用。

INode Keys

HDFS中的每個目錄和檔案都有一個唯一的INode,即使檔案被重命名或者移動到其它位置,該INode會保持不變。INode鍵是以檔案INode本身結尾,前面包含父INode的固定長度序列。

Key Definition: key(f) = <ppId, pId, selfId>

selfId是檔案的INodeId,pId是父目錄的INodeId,ppId是父目錄的父目錄的INodeId。INode鍵的這種表達不僅保證了同級,同時也保證了表親(相同祖父節點)在大多數情況下被分區到相同的範圍中。這些鍵基于INodeId而非檔案名,允許簡單的檔案和目錄進行重命名,稱為就地重命名,而無需重新進行分區。

效果

經過測試驗證使用和不使用FGL功能性能,在主要寫入操作情況下,吞吐量平均提高了25%左右。

詳細性能對比

使用Hadoop NN Benchmarking工具(NNThroughputBenchmark)來驗證NameNode的性能。每個寫入API驗證并觀察到平均25%的性能提升。有很少一部分輕微或者沒有提升的API,分析并發現這些API均是輕量級API,是以沒有太大的提升。

NNThroughputBenchmark是用于NameNode性能基準測試工具。該工具提供了非常基本的API調用,比如建立檔案,建立目錄、删除。在這個基礎上進行了增強,進而能夠支援所有寫入API,并能夠捕獲使用和不使用FGL的版本的性能資料。

用于測試的資料集:線程數 1000、檔案數 1000000、每個目錄檔案數 40。

寫入調用頻率高的API

HDFS 細粒度鎖優化,FusionInsight MRS有妙招

其它内部寫API

HDFS 細粒度鎖優化,FusionInsight MRS有妙招

常用讀取API:

通過完整的FGL實作,讀取API也有很好的性能提升。

HDFS 細粒度鎖優化,FusionInsight MRS有妙招

運作基準測試工具的指令:

./hadoop org.apache.hadoop.hdfs.server.namenode.NNThroughputBenchmark -fs file:/// -op create -threads 200 -files 1000000 -filesPerDir 40 –close

./hadoop org.apache.hadoop.hdfs.server.namenode.NNThroughputBenchmark -fs hdfs:x.x.x.x:dddd/hacluster -op create -threads 200 -files 1000000 -filesPerDir 40 -close

參考

與FGL相關的社群讨論

Hadoop Meetup Jan 2019 — HDFS Scalability and Consistent Reads from Standby Node, which covers Three-Stage Scalability Plan. Slides 21–25

社群中跟蹤與NameNode可擴充性相關的其它Jira

HDFS-5453. Support fine grain locking in FSNamesystem

HDFS-5477. Block manager as a service

HDFS-8286. Scaling out the namespace using KV store

HDFS-14703. Namenode Fine Grained Locking (design inspired us to implement it fully)

總結

華為雲FusionInsight MRS雲原生資料湖為政企客戶提供湖倉一體、雲原生的資料湖解決方案,建構一個架構可持續演進的離線、實時、邏輯三種資料湖,支撐政企客戶全量資料的實時分析、離線分析、互動查詢、實時檢索、多模分析、資料倉庫、資料接入和治理等大資料應用場景。

繼續閱讀