HDFS節點內數據平衡:DiskBalancer

前言


做集羣運維的同學可能都會遇到這樣一個問題:Hadoop集羣使用久了,各個節點上的數據會變得不均衡,多的達到70,80%,少的就10,20%.面對這種場景,我們的辦法一般就是用HDFS自帶的Balancer工具對其進行數據平衡.但有的時候,你會發現儘管節點間數據平衡了,但是節點內各個磁盤塊的數據出現了不平衡的現象.這可是Balancer工具所幹不了的事情.通過這個場景,我們引入本文的一個話題點:HDFS節點內數據平衡.這個問題很早的時候其實就被提出了,詳見issueHDFS-1312(Re-balance disks within a Datanode).我相信大家在使用Hadoop集羣的時候或多或少都遇到過這個問題.本文就來好好聊聊這個話題,以及社區目前對此的解決方案.

磁盤間數據不均衡狀況的出現


磁盤間數據不均衡的現象源自於長期寫操作時數據大小不均衡.因爲每次寫操作你可以保證寫磁盤的順序性,但是你沒法保證每次寫入的數據量都是一個大小.比如A,B,C,D四塊盤,你用默認的RoundRobin磁盤選擇策略去寫,最後四塊盤都寫過了,但是A,B可能寫的block塊就1M,而C,D可能就是128M.

磁盤間數據不均衡帶來的問題


如果磁盤間數據不均衡現象確實出現了,它會給我們造成什麼影響呢?有人可能會想,它不就是一個普通磁盤嘛,又不是系統盤,系統盤使用空間過高是會影響系統性能,但是普通盤應該問題不大吧.這個觀點聽上去是沒問題,但是隻能說它考慮的太淺了.我們從HDFS的讀寫層面來對這個現象做一個分析.這裏歸納出了以下2點:

第一點,磁盤間數據不均衡間接引發了磁盤IO壓力的不同.我們都知道,HDFS上的數據訪問頻率是很高的,這就會涉及到大量讀寫磁盤的操作,數據多的盤自然的就會有更高頻率的訪問操作.如果一塊盤的IO操作非常密集的話,勢必會對它的讀寫性能造成影響. 
第二點,高使用率磁盤導致節點可選存儲目錄減少.HDFS在寫Block數據的時候,會挑選剩餘可用空間滿足待寫Block的大小的情況下時,纔會進行挑選,如果高使用率磁盤目錄過多,會導致這樣的候選塊變少.所以這方面其實偏向的是對HDFS的影響.

磁盤間數據不均衡的傳統解決方案


磁盤間數據不均衡現象出現了,目前我們有什麼辦法解決呢?下面是2種現有解決方案:

方案一:節點下線再上線.將節點內數據不均衡的機器進行Decommision下線操作,下線之後再次上線.上線之後相當於是一個全新的節點了,數據也將會重新存儲到各個盤上.這種做法給人感覺會比較暴力,當集羣規模比較小的時候,代價太高,此時下線一個節點會對集羣服務造成不小的影響.

方案二:人工移動部分數據block存儲目錄.此方案比方案一更加靈活一些,但是數據目錄的移動要保證準確性,否則會造成移動完目錄後數據找不到的現象.下面舉一個實際的例子,比如我們想將磁盤1上的數據挪到磁盤2上.現有磁盤1的待移動存儲目錄如下:

/data/1/dfs/dn/ current/BP-1788246909-xx.xx.xx.xx-1412278461680/current/ finalized/subdir0/subdir1/

我移動到目標盤上的路徑應該維持這樣的路徑格式不變,只變化磁盤所在的目錄,目標路徑如下:

/data/2/dfs/dn/current/BP-1788246909-xx.xx.xx.xx-1412278461680/current/finalized/subdir0/subdir1/

如果上述目錄結構出現變化,就會造成HDFS找不到此數據塊的情況.

社區解決方案:DiskBalancer


前面鋪墊了這麼多的內容,就是爲了引出本節要重點闡述的內容:DiskBalancer.DiskBalancer從名字上,我們可以看出,它是一個類似於Balancer的數據平衡工具.但是它的作用範圍是被限制在了Disk上.首先這裏要說明一點,DiskBalancer目前是未發佈的功能特性,所以你們在現有發佈版中是找不到此工具的.下面我將會全方面的介紹DiskBalancer,讓大家認識,瞭解這個強大的工具.

DiskBalancer的設計核心


首先我們先來了解DiskBalancer的設計核心,這裏與Balancer有一點點的區別.Balancer的核心點在於數據的平衡,數據平衡好就OK了.而DiskBalancer在設計的時候提出了2點目標:

第一.Data Spread Report.數據分佈式的彙報.這是一個report彙報的功能.也就是說,DiskBalancer工具能支持各個節點彙報磁盤塊使用情況的功能,通過這個功能我可以瞭解到目前集羣內使用率TopN的節點磁盤. 
第二.Disk Balancing.第二點纔是磁盤數據的平衡.但是在磁盤內數據平衡的時候,要考慮到各個磁盤storageType的不同,因爲之前提到過HDFS的異構存儲,不同盤可能存儲介質會不同,目前DiskBalancer不支持跨存儲介質的數據轉移,所以目前都是要求在一個storageType下的.

以上2點取自於DiskBalancer的設計文檔(DiskBalancer相關設計文檔可見文章末尾的參考鏈接).

DiskBalancer的架構設計


此部分來討論討論DiskBalancer的架構設計.通過架構設計,我們能更好的瞭解它的一個整體情況.DiskBalancer的核心架構思想如下圖所示:

這裏寫圖片描述

上面過程經過了3個階段,Discover(發現)到Plan(計劃),再從Plan(計劃)到Execute(執行).下面來詳細解釋這3個階段:

Discover


發現階段做的事情實際上就是通過計算各個節點內的磁盤使用情況,然後得出需要數據平衡的磁盤列表.這裏會通過Volume Data Density磁盤使用密度的概念作爲一個評判的標準,這個標準值將會以節點總使用率作爲比較值.舉個例子,如果一個節點,總使用率爲75%,就是0.75,其中A盤使用率0.5(50%),那麼A盤的volumeDataDensity密度值就等於0.75-0.5=0.25.同理,如果超出的話,則密度值將會爲負數.於是我們可以用節點內各個盤的volumeDataDensity的絕對值來判斷此節點內磁盤間數據的平衡情況,如果總的絕對值的和越大,說明數據越不平衡,這有點類似於方差的概念.Discover階段將會用到如下的連接器對象:

1.DBNameNodeConnector 
2.JsonConnector 
3.NullConnector

其中第一個對象會調用到Balancer包下NameNodeConnector對象,以此來讀取集羣節點,磁盤數據情況

Plan


拿到上一階段的彙報結果數據之後,將會進行執行計劃的生成.Plan並不是一個最小的執行單元,它的內部由各個Step組成.Step中會指定好源,目標磁盤.這裏的磁盤對象是一層經過包裝的對象:DiskBalancerVolume,並不是原來的FsVolume.這裏順便提一下DiskBalancer中對磁盤節點等概念的轉化:

  • 1.DiskBalancerCluster.通過此對象可以,讀取到集羣中的節點信息,這裏的節點信息以DiskBalancerDataNode的方式所呈現.
  • 2.DiskBalancerDataNode.此對象代表的是一個包裝好後的DataNode.
  • 3.DiskBalancerVolume和DiskBalancerVolumeSet.DataNode磁盤對象以及磁盤對象集合.DiskBalancerVolumeSet內的磁盤存儲目錄類型需要是同種StorageType.

Execute


最後一部分是執行階段,所有的plan計劃生成好了之後,就到了執行階段.這些計劃會被提交到各自的DataNode上,然後在DiskBalancer類中進行執行.DiskBalancer類中有專門的類對象來做磁盤間數據平衡的工作,這個類名稱叫做DiskBalancerMover.在磁盤間數據平衡的過程中,高使用率的磁盤會移動數據塊到相對低使用率的磁盤,等到滿足一定閾值關係的情況下時,DiskBalancer會漸漸地退出.在DiskBalancer的執行階段,有以下幾點需要注意:

  • 1.帶寬的限制.DiskBalancer中同樣可以支持帶寬的限制,默認是10M,通過配置項dfs.disk.balancer.max.disk.throughputInMBperSec進行控制.
  • 2.失敗次數的限制.DiskBalancer中會存在失敗次數的控制.在拷貝block數據塊的時候,出現IOException異常,會進行失敗次數的累加計數,如果超出最大容忍值,DiskBalancer也會退出.
  • 3.數據平衡閾值控制.DiskBalancer中可以提供一個磁盤間數據的平衡閾值,以此作爲是否需要繼續平衡數據的標準,配置項爲dfs.disk.balancer.block.tolerance.percent.

DiskBalancer的命令執行


DiskBalancer內部提供了許多類別的命令操作,比如下面的查詢命令:

hdfs diskbalancer -query nodename.mycluster.com
  • 1
  • 1

我們也可以執行相應的plan命令來生成plan計劃文件.

hdfs diskbalancer -uri hdfs://mycluster.com -plan node1.mycluster.com
  • 1
  • 1

然後我們可以用生成好後的json文件進行DiskBalancer的執行

hdfs diskbalancer -execute /system/diskbalancer/nodename.plan.json
  • 1
  • 1

當然,如果我們發現我們執行了錯誤的plan,我們也可以通過cancel命令進行清除:

hdfs diskbalancer -cancel /system/diskbalancer/nodename.plan.json
  • 1
  • 1

hdfs diskbalancer -cancel <planID> -node <nodename>
  • 1
  • 1

在DiskBalancer中會涉及到比較多的object-json的關係轉換,所以你會看到一些帶.json後綴的文件

小結


總而言之,DiskBalancer是一個很實用的功能特性.在Hadoop中,有專門的分支用於開發此功能,就是HDFS-1312,感興趣的同學可以下載Hadoop的最新代碼進行學習.本人非常榮幸地也向此功能提交了一個小patch, issue編號,HDFS-10560.這個new feature很快就要在新版的Hadoop中發佈了,相信會對Hadoop集羣管理人員非常有幫助.

參考資料


1.https://issues.apache.org/jira/secure/attachment/12755226/disk-balancer-proposal.pdf 
2.https://issues.apache.org/jira/secure/attachment/12810720/Architecture_and_test_update.pdf 
2.https://issues.apache.org/jira/browse/HDFS-1312 
3.https://issues.apache.org/jira/browse/HDFS-10560

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章