成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

NameNode鎖細粒度優化在B站的實踐

大數據 數據可視化
NameNode是整個HDFS的核心組件,集中管理HDFS集群的所有元數據,主要包括文件系統的目錄樹、數據塊集合和分布以及整個集群的拓撲結構。

1. 背景

隨著業務的高速發展,針對HDFS元數據的訪問請求量呈指數級上升。在之前的工作中,我們已經通過引入HDFS Federation和Router機制實現NameNode的平行擴容,在一定程度上滿足了元數據的擴容需求;也通過引入Observer NameNode讀寫分離架構提升單組NameSpace的讀寫能力,在一定程度上減緩了讀寫壓力。但隨著業務場景的發展變化,NameSpace數量也在上升至30+組后,Active+Standby+Observer NameNode 的架構已經無法滿足所有的元數據讀寫場景,我們必須考慮提升NameNode讀寫能力,來應對不斷上升的元數據讀寫要求。

如圖1-1 所展示的B站離線存儲整體架構所示,隨著業務的不斷增量發展,通過引入HDFS Router機制實現NameNode的平行擴容,目前NameSpace的數量已經超過30+組,總存儲量EB級,每日請求訪問量超過200億次。各個NameSpace之間的讀寫請求更是分布非常不均衡,在一些特殊場景下,部分NameSpace的整體負載更高。如Flink任務的CheckPoint 場景,Spark和MR任務的log日志上傳場景,這兩類場景的數據寫入要求要遠遠高于普通場景。此外還有部分數據回刷場景,存在短時間寫入請求增加300%以上的情況,極易觸發NameNode的寫入性能瓶頸,影響其他任務的正常訪問。為了應對這個問題,我們針對性的提出了NameNode的讀寫性能提升方案。

圖1-1 B站HDFS整體架構圖圖1-1 B站HDFS整體架構圖

2. HDFS 細粒度鎖優化整體方案

2.1 面臨的問題

NameNode是整個HDFS的核心組件,集中管理HDFS集群的所有元數據,主要包括文件系統的目錄樹、數據塊集合和分布以及整個集群的拓撲結構。HDFS在對NameNode的實現上做了大膽取舍,如圖2-1所示,鎖機制上使用全局鎖來統一來控制并發讀寫。這樣處理的優勢非常明顯,全局鎖進一步簡化鎖模型,不需要額外考慮鎖依賴關系,同時降低復雜度,減少工程量。但是問題比優勢更加突出,核心問題就是全局唯一鎖制約性能提升。

圖2-1 B站HDFS整體架構圖圖片

在多年的HDFS實踐工作中,我們發現NameNode全局唯一的讀寫鎖已經成為NameNode讀寫性能最大瓶頸之一,社區已經做了很多的工作來優化相關性能,如將一些日志操作異步化,移動日志操作到鎖外,針對DU請求采用分段鎖,大刪除異步化等一系列優化措施,但對于我們這種數據量的HDFS集群來說,仍然難以滿足部分生產場景。為了進一步提升HDFS讀寫性能,滿足業務場景,我們計劃對全局鎖進行細粒度拆分,為此我們也面臨著許多困難。

首先是問題復雜度高,Hadoop發展到今天已經超過十年,其中HDFS經過多次迭代演進,架構已經非常復雜。針對NameNode組件來說,架構上模塊劃分不夠清晰,內部核心數據結構和工作線程之間耦合非常嚴重,實現細節上,還存在大量相互依賴,不一而足。

其次是社區的動力不足,在全局唯一的讀寫鎖的擴展性問題上,社區做過多次嘗試,主要就有 HDFS-8966:Separate the lock used in namespace and block management layer 和 HDFS-5453:Support fine grain locking in FSNamesystem 等方面的嘗試,但是并沒有產出可以進行生產化部署的成果。具體原因還是動力不足,因為NameNode性能針對小規模部署的集群來說大體上已經足夠,也有通過Federation和Router機制進行擴展,滿足一定的需求。

為了解決這個難題,我們參考了業界的拆鎖方案和Alluxio的LockPool實現機制,計劃實現針對NameNode全局唯一鎖的細粒度拆分。

2.2 設計選型

為了更好地理解使用全局鎖存在的問題,首先梳理全局鎖管理的主要數據結構,大致分成三類:

  • NameSpace目錄樹:文件系統的全局目錄視圖。獲取目錄樹上任一節點的信息必須先拿到全局讀鎖;目錄樹上任一節點新增、刪除、修改都必須先拿到全局寫鎖。
  • BlockPool層數據塊集合:文件系統的全量數據信息。獲取其中任一數據塊信息必須先拿到全局讀鎖;新增、刪除,修改都必須先拿到全局寫鎖。
  • 集群信息:HDFS集群節點信息的集合。獲取節點信息等必須先拿到全局讀鎖;注冊,下線或者變更節點信息請求處理時必須先拿到全局寫鎖。

具體實現上,NameNode使用了JDK提供的可重入讀寫鎖(ReentrantReadWriteLock),ReentrantReadWriteLock對并行請求有嚴格限制,支持讀請求并行處理,寫請求具有排他性。針對不同RPC請求的處理邏輯,按照需要獲取鎖粒度,我們可以把所有請求抽象為全局讀鎖和全局寫鎖兩類。全局讀鎖包括客戶端請求(getListing/getBlockLocations/getFileInfo)、服務管理接口(monitorHealth/getServiceStatus)等;全局寫鎖則包括客戶端寫請求(create/mkdir/rename/append/truncate/complete/recoverLease)、服務管理接口(transitionToActive/transitionToStandby/setSafeMode)和主從節點之間請求(rollEditLog)等。在一次RPC處理過程中,如果不能及時獲取到鎖,這次RPC將處于排隊等待狀態,直到成功獲得鎖,鎖等待時間直接影響請求響應性能,極端場景下如果長時間不能獲得鎖,將造成IPC隊列堆積,TCP連接隊列被打滿,客戶端出現請求卡住,新建連接超時失敗等各種異常問題。從全局來看,寫鎖因為排它對性能影響更加明顯。如果當前有寫請求正在被處理,其他所有請求都必須排隊等待,直到寫請求被處理完成釋放鎖后再競爭全局鎖。因此我們希望對全局鎖進行細粒度劃分,最終實現NameNode服務的大部分的RPC請求都能并行處理。

我們計劃通過3步實現 NameNode 鎖的細粒度劃分,如圖2-2所示。

第一步,將NameNode 全局鎖拆分為 Namespace層讀寫鎖和 BlockPool層讀寫鎖;

第二部,將NameSpace讀寫鎖拆成顆粒度更細的Inode層的讀寫鎖;

第三步,將BlockPool層讀寫鎖也拆成更細粒度的讀寫鎖;

目前我們已經基本完成第一部分和第二部分的工作。

圖2-2 NameNode 鎖優化過程圖2-2 NameNode 鎖優化過程


3. HDFS 細粒度鎖優化實現

3.1 NameNode全局唯一鎖拆成

NameSpace層鎖和BlockPool層鎖

在實踐中發現,客戶端請求訪問NameNode過程中,部分請求需要同時訪Namespace層和BlockPool層,有些請求只需要訪問 Namespace層,同時服務端請求如DataNode的IBR/BlockReport等請求實際上也只需要訪問 BlockPool層,這兩層的鎖調用可以拆分,實現對兩層數據的并行訪問。因此拆鎖的第一步, 就是將NameNode 全局鎖拆分為 Namespace層讀寫鎖和 BlockPool層讀寫鎖,如圖2-3所示,通過這種拆分實現訪問的這兩層數據的RPC請求能夠并?處理。在實踐過程中,我們引入了BlockManagerLock,單獨處理BlockPool層鎖事件。

圖2-3 NameNode全局唯一鎖拆成NameSpace層鎖和BlockPool層鎖圖2-3 NameNode全局唯一鎖拆成NameSpace層鎖和BlockPool層鎖

在實際的拆鎖過程中,我們發現NameSpace層和BlockPool層之間有非常多的耦合,這里我們參考了社區的一部分工作HDFS-8966:Separate the lock used in namespace and block management layer, 已經幫助我們解除了部分的依賴,除了社區列出來的這部分依賴之外我們還發現一些BlockPool層對NameSpace層的反相依賴,主要是Block的副本信息和storagePolicy屬性信息,這塊我們將這部分信息在BlockPool層進行冗余存儲,同時確保發生變更時NameSpace層的信息及時同步至BlockPool層。在解除了BlockPool層對NameSpace層的反相依賴后,開始針對不同類型的請求獲取何種類型的鎖進行區分,如圖2-4所示。

  • NameSpace層請求(getListing/getFileInfo等請求),只需要獲取NameSpace層鎖;
  • BlockPool層請求(BlockReport/IncrementalBlockReport等請求),只需要獲取BlockPool層鎖,這塊我們發現有塊上報過程中,有一段更新Quota的邏輯需要獲取NameSpace層鎖,我們無法做到完美的適配,考慮到我們的Quota采用的外置計算的方式,所以做了相應的取舍,只獲取了BlockPool層的鎖;
  • 同時訪問NameSpace層和BlockPool層的請求(setReplication/getBlockLocation),需要同時獲取NameSpace層的鎖和BlockPool層的鎖。

通過對不同請求按不同類型鎖要求劃分后,我們基本可以做到訪問部分不同層數據的請求的并行執行,但仍然有2個問題需要解決。首先是死鎖問題,為此我們確保所有請求的加鎖順序的一致性,所有需要同時獲取NameSpace層鎖和BlockPool層的請求都是NameSpace層鎖在前,BlockPool層的鎖在后;其次是一致性問題,NameNode內部本身是寫一致性,并發讀取場景,針對同時訪問NameSpace層和BlockPool層的請求,需要確保NameSpace層加鎖范圍完全包含BlockPool層加鎖范圍,防止讀取到中間狀態。

圖2-4 不同類型的請求加鎖場景圖2-4 不同類型的請求加鎖場景

通過上述這種方式,我們基本實現了BlockPool層和NameSpace層的鎖拆分,當前這部分優化策略已經在生產環境運行了一段時間,NameNode整體性能大約提升了50%左右。

3.2 NameSpace層鎖拆分成INode粒度鎖

在實現了FSN層和BP層鎖拆分之后,NameNode性能已經有了一定的提升,生產環境中對HDFS的NameNode元數據請求的rpc processtime和queuetime也有明顯的下降,但仍然有一些場景無法滿足,因此我們繼續優化,對NameSpace層的鎖進行更細粒度的拆分如圖2-5所示,將鎖細粒度到INode層,希望能進一步提升NameSpace層RPC并發能力,提升NameNode整體寫入能力。

圖2-5 NameSpace層鎖細粒度拆分圖2-5 NameSpace層鎖細粒度拆分

要將NameSpace層鎖拆分到INode層級粒度,必然要為對應的INode分配鎖對象,在這里我們面臨了許多問題。

首先是內存限制,我們目前單組Namespace元數據容量閾值基本在10億左右,如果每個INode分配一個INode鎖,單是INode鎖的內存幾乎就需要120GB左右的內存,再加上本身NameNode就非常耗費內存,當前的服務器類型很難滿足。為了解決這個問題,我們參考了 Alluxio 的LockPool 的概念,也就是有一個鎖資源池,每個INode需要Lock加鎖的時候,就去資源池里申請鎖,同時引用計數會增加,用完之后unlock掉的時候,引用計數會減少,同時配置不同的高低水位,定期清理掉引用計數為0的鎖,確保總體內存可控。

其次是鎖對象的管理,這方面我們引入了INodeLockManager 用于管理INode和鎖對象的之間的映射,我們通過INodeLockManager新增了INode鎖的LockPool 和 Edge鎖的LockPool,如圖2-6所示,管理整個NameSpace層的INode層級的細粒度鎖。

圖2-6 NameSpace層的INode層級的細粒度鎖管理圖2-6 NameSpace層的INode層級的細粒度鎖管理

完成了鎖對象的管理后,Namespace層鎖細粒度拆分剩下的問題都是如何預防死鎖和數據錯亂,因此我們對加鎖行為進行規劃,總體遵循如下原則。

  • 普通Client端的RPC請求采用自上而下的加鎖方式,對特殊操作如Rename等操作進行特殊處理;
  • Client端的RPC請求進行全鏈路加鎖,部分請求考慮最后的INode和Edge加寫鎖;

如圖2-7所示,我們配置了3種類型的鎖,分別時Read鎖,Write_Inode 鎖和 WRITE_EDGE鎖分別應對不同類型的客戶端RPC請求。針對讀請求,我們正向遍歷INodeTree從ROOT節點開始依次加鎖 對對整個路徑上的INode和Edge都加讀鎖;針對addBlock ,setReplication 這類不影響INodeTree的請求,我們也是正向遍歷INodeTree從ROOT節點開始依次加讀鎖,但是對最后一個INode加寫鎖;針對create ,mkdir請求,我們正向遍歷INodeTree ,對最后INode節點和最后的Edge都加寫鎖,如果最后INode不存在,對最后的Edge也需要加寫鎖。

圖2-7 INodeLock 加鎖方式圖2-7 INodeLock 加鎖方式

除了訪問單個路徑的請求,還有rename等訪問多個路徑的rpc請求,如圖2-8所示,從 /a/b/c rename 成 /a/b/e,我們對這種場景做了特殊處理。我們首先路徑/a/b/c和/a/b/e按字典序確定先后,再自上而下加鎖,如圖2-8所示,路徑/a/b/c排序在前,我們先對/a/b/c 路徑加鎖,正向遍歷INodeTree從ROOT節點開始依次加鎖,邊b-c,INode c都加上寫鎖,路徑/a/b/e排序在后,我們在對路徑/a/b/c加鎖完成后,對路徑/a/b/e加鎖,同樣遍歷INodeTree,Edge b→e加上寫鎖,INode e 由于還未存在,則放棄加鎖;

圖2-8 Rename RPC操作加鎖方式圖2-8 Rename RPC操作加鎖方式

在上述的工作中,我們完成了不同請求的加鎖方式,針對部份加鎖場景中存在的INode缺失場景(如文件不存在等場景),如下圖2-9所示針對相對典型的是create請求列舉了不同RPC類型的加鎖邏輯。

  • create 路徑/a/b/c文件,如果當前已經存在存在/a/b 路徑,則最終會在Edge b->c 加寫鎖;
  • create 路徑/a/b/c文件,如果已經存在/a/b/c路徑,則最終會在Edge b→c 和INode c上加寫鎖;
  • create 路徑/a/b/c文件,如果只存在 /a 路徑,則會在Edge a->b 這條邊上加上寫鎖。

圖 2-9 不同RPC類型的加鎖邏輯舉例圖 2-9 不同RPC類型的加鎖邏輯舉例

通過實現上述2步拆鎖過程,NameNode性能已經有了很大提升,如圖2-10展示了我們在測試環境中的性能對比,經過Namespace層讀寫鎖和BlockPool層讀寫鎖拆分后,相比于社區版本,單NameSpace的寫性能大約提升了50% ,經過Namespace層細粒度鎖拆分后,寫性能相比于社區版本有3倍左右的提升,此時NameNode性能瓶頸已經集中在Edits和審計日志同步以及BlockPool層的本身的鎖競爭上。在實際生產過程中,我們把之前需要2組NameSpace支持的任務日志采集路徑收歸為一組NamesSpace支持,在寫入QPS上升3倍的場景下,整體rpc queue time 下降了90%,整體性能有很大的提升。

圖2-10 鎖優化性能對比圖2-10 鎖優化性能對比

四. 總結與展望

NameNode的性能優化已經告一段落了,第一步和第二部的拆鎖已經在我們的生產集群上穩定運行了一段時間,整體性能提升明顯,整體RPC Queue Time相比于拆鎖之前有數量級的下降,當前已經可以支持絕大多數應用場景,包括之前的描述的任務日志聚合和Flink CheckPoint 路徑等場景,在接下來計劃中,我們也正在考慮是否將BlockPool層鎖做進一步細粒度拆分,進一步提升NameNode的性能。

同時考慮到NameNode元數據都存儲在內存中,限制了NameNode元數據總量的擴展,特別是小文件場景,我們也將在未來規劃引入Ozone或者將NameNode的元數據信息持久化至RocksDB或者KV中,進一步提升單組Namespace的承載量徹底解決小文件問題。

責任編輯:武曉燕 來源: 嗶哩嗶哩技術
相關推薦

2024-06-27 08:00:00

存儲數據庫細粒度

2010-04-19 09:35:58

Oracle細粒度

2009-04-16 17:59:25

細粒度權限

2010-04-14 11:04:53

Oracle細粒度

2009-10-27 09:31:24

Windows Ser口令策略

2010-04-16 16:39:25

Oracle細粒度

2010-04-22 13:39:31

Oracle細粒度訪問

2018-02-25 04:05:16

2018-08-23 09:10:01

數據庫MySQLInnoDB

2010-12-30 14:34:43

云計算供應商

2018-02-07 14:53:42

2018-08-27 07:29:34

InnoDBinsertselect

2019-10-29 16:10:55

死鎖Java并發

2024-08-13 12:54:20

2010-10-20 15:09:05

2022-06-27 17:58:42

pwrueBPF工具

2025-02-18 09:10:00

2023-02-28 12:12:21

語音識別技術解碼器

2009-03-31 11:20:10

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 鸳鸯谱在线观看高清 | 91国在线高清视频 | 青青久久 | 成人三级av | 国产精品久久久久久久免费观看 | 免费a大片 | 91av免费看| 日韩中文字幕一区二区 | 午夜精品影院 | 国产精品久久一区 | 精品96久久久久久中文字幕无 | 婷婷在线视频 | 国产一级在线 | 中文字幕成人在线 | 在线观看中文字幕 | 天堂网中文 | 亚洲欧洲一区 | 久草免费在线视频 | 国产成人精品999在线观看 | 欧美激情精品久久久久 | 亚洲精品自在在线观看 | 国产成人精品午夜视频免费 | 国产精品精品久久久久久 | 精品国产乱码久久久久久老虎 | 秋霞电影一区二区三区 | 天天操人人干 | 伊人艹| 欧洲一级毛片 | 亚欧午夜 | 香蕉一区二区 | 久久狠狠 | 欧美亚洲另类丝袜综合网动图 | av天天看 | 水蜜桃久久夜色精品一区 | 国产一区二区在线播放 | 涩涩视频在线看 | 日韩网站免费观看 | 亚洲精品68久久久一区 | 日韩欧美在线一区 | 欧美一区二区免费 | 精品国产乱码久久久久久蜜柚 |