HDFS 副本存放磁盤選擇策略詳解
在 HDFS 中,DataNode 將數據塊存儲到本地文件系統目錄中,具體的目錄可以通過配置 hdfs-site.xml 里面的 dfs.datanode.data.dir 參數。在典型的安裝配置中,一般都會配置多個目錄,并且把這些目錄分別配置到不同的設備上,比如分別配置到不同的HDD(HDD的全稱是Hard Disk Drive)和SSD(全稱Solid State Drives,就是我們熟悉的固態硬盤)上。
當我們往 HDFS 上寫入新的數據塊,DataNode 將會使用 volume 選擇策略來為這個塊選擇存儲的地方。通過參數 dfs.datanode.fsdataset.volume.choosing.policy 來設置,這個參數目前支持兩種磁盤選擇策略。
- round-robin
- available space
如果想及時了解Spark、Hadoop或者Hbase相關的文章,歡迎關注微信公共帳號:iteblog_hadoop
dfs.datanode.fsdataset.volume.choosing.policy 參數的默認值是 org.apache.hadoop.hdfs.server.datanode.fsdataset.AvailableSpaceVolumeChoosingPolicy。這兩種磁盤選擇策略都是對 org.apache.hadoop.hdfs.server.datanode.fsdataset.VolumeChoosingPolicy 接口進行實現,VolumeChoosingPolicy 接口其實就定義了一個函數:chooseVolume 如下:
chooseVolume 函數對指定的副本從 volumes 里面選定滿足條件的磁盤。下面對 Hadoop 內置的兩種磁盤選擇策略進行詳細的介紹。
round-robin 磁盤選擇策略
從名字就可以看出,這種磁盤選擇策略是基于輪詢的方式,具體的實現類是 org.apache.hadoop.hdfs.server.datanode.fsdataset.RoundRobinVolumeChoosingPolicy。它的實現很簡單:
volumes 參數其實就是通過 dfs.datanode.data.dir 配置的目錄。blockSize 就是咱們副本的大小。RoundRobinVolumeChoosingPolicy 策略先輪詢的方式拿到下一個 volume ,如果這個 volume 的可用空間比需要存放的副本大小要大,則直接返回這個 volume 用于存放數據;如果當前 volume 的可用空間不足以存放副本,則以輪詢的方式選擇下一個 volume,直到找到可用的 volume,如果遍歷完所有的 volumes 還是沒有找到可以存放下副本的 volume,則拋出 DiskOutOfSpaceException 異常。
從上面的策略可以看出,這種輪詢的方式雖然能夠保證所有磁盤都能夠被使用,但是如果 HDFS 上的文件存在大量的刪除操作,可能會導致磁盤數據的分布不均勻,比如有的磁盤存儲得很滿了,而有的磁盤可能還有很多存儲空間沒有得到利用。
available space 磁盤選擇策略
可用空間磁盤選擇策略是從 Hadoop 2.1.0 開始引入的(詳情參見:HDFS-1804)。這種策略優先將數據寫入具有***可用空間的磁盤(通過百分比計算的)。在實現上可用空間選擇策略內部用到了上面介紹的輪詢磁盤選擇策略,具體的實現代碼在 org.apache.hadoop.hdfs.server.datanode.fsdataset.AvailableSpaceVolumeChoosingPolicy 類中,核心實現如下:
areAllVolumesWithinFreeSpaceThreshold 函數的作用是先計算所有 volumes 的***可用空間和最小可用空間,然后使用***可用空間減去最小可用空間得到的結果和 balancedSpaceThreshold(通過 dfs.datanode.available-space-volume-choosing-policy.balanced-space-threshold 參數進行配置,默認值是 10G) 進行比較。
可用空間策略會以下面三種情況進行處理:
1、如果所有的 volumes 磁盤可用空間都差不多,那么這些磁盤得到的***可用空間和最小可用空間差值就會很小,這時候就會使用輪詢磁盤選擇策略來存放副本。
2、如果 volumes 磁盤可用空間相差比較大,那么可用空間策略會將 volumes 配置中的磁盤按照一定的規則分為 highAvailableVolumes 和 lowAvailableVolumes。具體分配規則是先獲取 volumes 配置的磁盤中最小可用空間,加上 balancedSpaceThreshold(10G),然后將磁盤空間大于這個值的 volumes 放到 highAvailableVolumes 里面;小于等于這個值的 volumes 放到 lowAvailableVolumes 里面。
比如我們擁有5個磁盤組成的 volumes,編號和可用空間分別為 1(1G)、2(50G)、3(25G)、4(5G)、5(30G)。按照上面的規則,這些磁盤的最小可用空間為 1G,然后加上 balancedSpaceThreshold,得到 11G,那么磁盤編號為1、4的磁盤將會放到 lowAvailableVolumes 里面,磁盤編號為2,3和5將會放到 highAvailableVolumes 里面。
到現在 volumes 里面的磁盤已經都分到 highAvailableVolumes 和 lowAvailableVolumes 里面了。
2.1、如果當前副本的大小大于 lowAvailableVolumes 里面所有磁盤***的可用空間(mostAvailableAmongLowVolumes,在上面例子中,lowAvailableVolumes 里面***磁盤可用空間為 5G),那么會采用輪詢的方式從 highAvailableVolumes 里面獲取相關 volumes 來存放副本。
2.2、剩下的情況會以 75%(通過 dfs.datanode.available-space-volume-choosing-policy.balanced-space-preference-fraction 參數進行配置,推薦將這個參數設置成 0.5 到 1.0 之間)的概率在 highAvailableVolumes 里面以輪詢的方式 volumes 來存放副本;25% 的概率在 lowAvailableVolumes 里面以輪詢的方式 volumes 來存放副本。
然而在一個長時間運行的集群中,由于 HDFS 中的大規模文件刪除或者通過往 DataNode 中添加新的磁盤仍然會導致同一個 DataNode 中的不同磁盤存儲的數據很不均衡。即使你使用的是基于可用空間的策略,卷(volume)不平衡仍可導致較低效率的磁盤I/O。比如所有新增的數據塊都會往新增的磁盤上寫,在此期間,其他的磁盤會處于空閑狀態,這樣新的磁盤將會是整個系統的瓶頸。