Hdfs存儲策略

一、磁盤選擇策略

1.1、介紹

在HDFS中,所有的數據都是存在各個DataNode上的.而這些DataNode上的數據都是存放於節點機器上的各個目錄中的,而一般每個目錄我們會對應到1個獨立的盤,以便我們把機器的存儲空間基本用上.這麼多的節點,這麼多塊盤,HDFS在進行寫操作時如何進行有效的磁盤選擇呢

HDFS目前的2套磁盤選擇策略都是圍繞着"數據均衡"的目標設計的:RoundRobinVolumeChoosingPolicy和AvailableSpaceVolumeChoosingPolicy

1.2、RoundRobinVolumeChoosingPolicy

名稱可以拆成2個單詞,RoundRobin和VolumeChoosingPolicy,VolumeChoosingPolicy理解爲磁盤選擇策略,RoundRobin這個是一個專業術語,叫做"輪詢",類似的還有一些別的類似的術語,Round-Robin Scheduling(輪詢調度),Round-Robin 算法等.RoundRobin輪詢的意思用最簡單的方式翻譯就是一個一個的去遍歷,到尾巴了,再從頭開始。

理論上來說這種策略是蠻符合數據均衡的目標的,因爲一個個的寫嗎,每塊盤寫入的次數都差不多,不存在哪塊盤多寫少寫的現象,但是唯一的不足之處在於每次寫入的數據量是無法控制的,可能我某次操作在A盤上寫入了512字節的數據,在輪到B盤寫的時候我寫了128M的數據,數據就不均衡了,所以說輪詢策略在某種程度上來說是理論上均衡但還不是最好的。

實現很簡單:

volumes 參數其實就是通過 dfs.datanode.data.dir 配置的目錄。blockSize 就是咱們副本的大小。RoundRobinVolumeChoosingPolicy 策略先輪詢的方式拿到下一個 volume ,如果這個 volume 的可用空間比需要存放的副本大小要大,則直接返回這個 volume 用於存放數據;如果當前 volume 的可用空間不足以存放副本,則以輪詢的方式選擇下一個 volume,直到找到可用的 volume,如果遍歷完所有的 volumes 還是沒有找到可以存放下副本的 volume,則拋出 DiskOutOfSpaceException 異常。

從上面的策略可以看出,這種輪詢的方式雖然能夠保證所有磁盤都能夠被使用,但是如果 HDFS 上的文件存在大量的刪除操作,可能會導致磁盤數據的分佈不均勻,比如有的磁盤存儲得很滿了,而有的磁盤可能還有很多存儲空間沒有得到利用。

1.3、AvailableSpaceVolumeChoosingPolicy

剩餘可用空間磁盤選擇策略.這個磁盤選擇策略比第一種設計的就精妙很多了,首選他根據1個閾值,將所有的磁盤分爲了2大類,高可用空間磁盤列表和低可用空間磁盤列表.然後通過1個隨機數概率,會比較高概率下選擇高剩餘磁盤列表中的塊,然後對這些磁盤列表進行輪詢策略的選擇。

可用空間磁盤選擇策略是從 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。比如所有新增的數據塊都會往新增的磁盤上寫,在此期間,其他的磁盤會處於空閒狀態,這樣新的磁盤將會是整個系統的瓶頸

1.4、相關配置

dfs.datanode.fsdataset.volume.choosing.policy:The class name of the policy for choosing volumes in the list of directories. Defaults to org.apache.hadoop.hdfs.server.datanode.fsdataset.RoundRobinVolumeChoosingPolicy. If you would like to take into account available disk space, set the value to "org.apache.hadoop.hdfs.server.datanode.fsdataset.AvailableSpaceVolumeChoosingPolicy".。這兩種磁盤選擇策略都是對 org.apache.hadoop.hdfs.server.datanode.fsdataset.VolumeChoosingPolicy 接口進行實現。

dfs.datanode.available-space-volume-choosing-policy.balanced-space-threshold:默認值(10737418240:10G)只有在AvailableSpaceVolumeChoosingPolicy配置下才生效,

dfs.datanode.available-space-volume-choosing-policy.balanced-space-preference-fraction:默認值(0.75f)只有在AvailableSpaceVolumeChoosingPolicy配置下才生效


參考網址:https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-hdfs/hdfs-default.xml

https://blog.csdn.net/weixin_41076809/article/details/80047557

https://blog.csdn.net/androidlushangderen/article/details/50531760

二、存儲策略

2.1、存儲類型

DISK:默認的存儲類型,磁盤存儲
ARCHIVE:具有存儲密度高(PB級),但計算能力小的特點,可用於支持檔案存儲。
SSD:固態硬盤
RAM_DISK:DataNode中的內存空間

HDFS中是定義了這4種類型,SSD,DISK一看就知道是什麼意思,這裏看一下其餘的2個,RAM_DISK,其實就是Memory內存,而ARCHIVE並沒有特指哪種存儲介質,主要的指的是高密度存儲數據的介質來解決數據量的容量擴增的問題.這4類是被定義在了StorageType類中:

public enum StorageType { // sorted by the speed of the storage types, from fast to slow RAM_DISK(true), SSD(false), DISK(false), ARCHIVE(false); ...

旁邊的true或者false代表的是此類存儲類型是否是transient特性的.transient的意思是指轉瞬即逝的,並非持久化的.在HDFS中,如果沒有主動聲明數據目錄存儲類型的,默認都是DISK,配置屬性dfs.datanode.data.dir中進行本地對應存儲目錄的設置,同時帶上一個存儲類型標籤,聲明此目錄用的是哪種類型的存儲介質,例子如下:

[SSD]file:///grid/dn/ssd0

如果目錄前沒有帶上[SSD]/[DISK]/[ARCHIVE]/[RAM_DISK]這4種中的任何一種,則默認是DISK類型.

2.2、存儲原理

  1. DataNode通過心跳彙報自身數據存儲目錄的StorageType給NameNode,

  2. 隨後NameNode進行彙總並更新集羣內各個節點的存儲類型情況

  3. 待複製文件根據自身設定的存儲策略信息向NameNode請求擁有此類型存儲介質的DataNode作爲候選節點

2.3、存儲類型選擇策略

HDFS中提供熱、暖、冷、ALL_SSD、One_SSD、Lazy_Persistence等存儲策略。爲了根據不同的存儲策略將文件存儲在不同的存儲類型中,引入了一種新的存儲策略概念。HDFS支持以下存儲策略:

6種策略:

  1. Hot - for both storage and compute. The data that is popular and still being used for processing will stay in this policy. When a block is hot, all replicas are stored in DISK.
  2. Cold - only for storage with limited compute. The data that is no longer being used, or data that needs to be archived is moved from hot storage to cold storage. When a block is cold, all replicas are stored in ARCHIVE.
  3. Warm - partially hot and partially cold. When a block is warm, some of its replicas are stored in DISK and the remaining replicas are stored in ARCHIVE.
  4. All_SSD - for storing all replicas in SSD.
  5. One_SSD - for storing one of the replicas in SSD. The remaining replicas are stored in DISK.
  6. Lazy_Persist - for writing blocks with single replica in memory. The replica is first written in RAM_DISK and then it is lazily persisted in DISK.

熱(hot)

  • 用於大量存儲和計算

  • 當數據經常被使用,將保留在此策略中

  • 當block是hot時,所有副本都存儲在磁盤中。

冷(cold)

  • 僅僅用於存儲,只有非常有限的一部分數據用於計算

  • 不再使用的數據或需要存檔的數據將從熱存儲轉移到冷存儲中

  • 當block是cold時,所有副本都存儲在Archive中

溫(warm)

  • 部分熱,部分冷

  • 當一個塊是warm時,它的一些副本存儲在磁盤中,其餘的副本存儲在Archive中

全SSD

  • 將所有副本存儲在SSD中

單SSD

  • 在SSD中存儲一個副本,其餘的副本存儲在磁盤中。

懶持久

  • 用於編寫內存中只有一個副本的塊。副本首先寫在RAM_Disk中,然後惰性地保存在磁盤中。

HDFS存儲策略由以下字段組成:

  1. 策略ID(Policy ID)

  2. 策略名稱(Policy Name)

  3. 塊放置的存儲類型列表(Block Placement)

  4. 用於創建文件的後備存儲類型列表(Fallback storages for creation)

  5. 用於副本的後備存儲類型列表(Fallback storages for replication)

當有足夠的空間時,塊副本將根據#3中指定的存儲類型列表存儲。當列表#3中的某些存儲類型耗盡時,將分別使用#4和#5中指定的後備存儲類型列表來替換空間外存儲類型,以便進行文件創建和副本。

以下是一個典型的存儲策略表格:

Policy ID Policy Name Block Placement (n replicas) Fallback storages for creation Fallback storages for replication
15 Lazy_Persist RAM_DISK: 1, DISK: n-1 DISK DISK
12 All_SSD SSD: n DISK DISK
10 One_SSD SSD: 1, DISK: n-1 SSD, DISK SSD, DISK
7 Hot (default) DISK: n ARCHIVE
5 Warm DISK: 1, ARCHIVE: n-1 ARCHIVE, DISK ARCHIVE, DISK
2 Cold ARCHIVE: n
1 Provided PROVIDED: 1, DISK: n-1 PROVIDED, DISK PROVIDED, DISK

注意事項:

  1. Lazy_Persistence策略僅對單個副本塊有用。對於具有多個副本的塊,所有副本都將被寫入磁盤,因爲只將一個副本寫入RAM_Disk並不能提高總體性能。

  2. 對於帶條帶的擦除編碼文件,合適的存儲策略是ALL_SSD、HOST、CORD。因此,如果用戶爲EC文件設置除上述之外的策略,在創建或移動塊時不會遵循該策略。

2.4、命令

hdfs storagepolicies -help
$ hdfs storagepolicies -help
[-listPolicies]
List all the existing block storage policies.
[-setStoragePolicy -path <path> -policy <policy>]
Set the storage policy to a file/directory.
<path>    The path of the file/directory to set storage policy 
<policy>  The name of the block storage policy                 
[-getStoragePolicy -path <path>]
Get the storage policy of a file/directory.
<path>  The path of the file/directory for getting the storage policy

1個設置命令,2個獲取命令,最簡單的使用方法是事先劃分好冷熱數據存儲目錄。設置好對應的Storage Policy,然後後續相應的程序在對應分類目錄下寫數據,自動繼承父目錄的存儲策略。在較新版的Hadoop發佈版本中增加了數據遷移工具(hdfs mover -help)。此工具的重要用途在於他會掃描HDFS上的文件,判斷文件是否滿足其內部設置的存儲策略,如果不滿足,就會重新遷移數據到目標存儲類型節點上。

列出所有存儲策略:hdfs storagepolicies -listPolicies

[root@node1 Examples]# hdfs storagepolicies -listPolicies
Block Storage Policies:
        BlockStoragePolicy{PROVIDED:1, storageTypes=[PROVIDED, DISK], creationFallbacks=[PROVIDED, DISK], replicationFallbacks=[PROVIDED, DISK]}
        BlockStoragePolicy{COLD:2, storageTypes=[ARCHIVE], creationFallbacks=[], replicationFallbacks=[]}
        BlockStoragePolicy{WARM:5, storageTypes=[DISK, ARCHIVE], creationFallbacks=[DISK, ARCHIVE], replicationFallbacks=[DISK, ARCHIVE]}
        BlockStoragePolicy{HOT:7, storageTypes=[DISK], creationFallbacks=[], replicationFallbacks=[ARCHIVE]}
        BlockStoragePolicy{ONE_SSD:10, storageTypes=[SSD, DISK], creationFallbacks=[SSD, DISK], replicationFallbacks=[SSD, DISK]}
        BlockStoragePolicy{ALL_SSD:12, storageTypes=[SSD], creationFallbacks=[DISK], replicationFallbacks=[DISK]}
        BlockStoragePolicy{LAZY_PERSIST:15, storageTypes=[RAM_DISK, DISK], creationFallbacks=[DISK], replicationFallbacks=[DISK]}

設置存儲策略:hdfs storagepolicies -setStoragePolicy -path -policy

-path 引用目錄或文件的路徑
-policy 存儲策略的名稱

取消存儲策略:取消文件或目錄的存儲策略。在執行unset命令之後,將應用當前目錄最近的祖先存儲策略,如果沒有任何祖先的策略,則將應用默認的存儲策略。

hdfs storagepolicies -unsetStoragePolicy -path

-path 引用目錄或文件的路徑

獲取存儲策略:hdfs storagepolicies -getStoragePolicy -path

-path 引用目錄或文件的路徑。

2.5、配置

  • dfs.storage.policy.enabled:啓用/禁用存儲策略功能。默認值是true

  • dfs.datanode.data.dir:在每個數據節點上,應當用逗號分隔的存儲位置標記它們的存儲類型。這允許存儲策略根據策略將塊放置在不同的存儲類型上。

磁盤上的DataNode存儲位置/grid/dn/disk 0應該配置爲[DISK]file:///grid/dn/disk0
SSD上的DataNode存儲位置/grid/dn/ssd 0應該配置爲 [SSD]file:///grid/dn/ssd0
存檔上的DataNode存儲位置/grid/dn/Archive 0應該配置爲 [ARCHIVE]file:///grid/dn/archive0
將RAM_磁盤上的DataNode存儲位置/grid/dn/ram0配置爲[RAM_DISK]file:///grid/dn/ram0
如果DataNode存儲位置沒有顯式標記存儲類型,它的默認存儲類型將是磁盤。

2.6、冷熱溫三階段數據存儲

爲了更加充分的利用存儲資源,我們可以將數據分爲冷、熱、溫三個階段來存儲。

/data/hdfs-test/data_phase/hot 熱階段數據
/data/hdfs-test/data_phase/warm 溫階段數據
/data/hdfs-test/data_phase/cold 冷階段數據

配置存儲目錄:

進入到Hadoop配置目錄,編輯hdfs-site.xml

<property>
  <name>dfs.datanode.data.dir</name>
  <value>[DISK]file:///export/server/hadoop-3.1.4/data/datanode,ARCHIVE]file:///export/server/hadoop-3.1.4/data/archive</value>
  <description>DataNode存儲名稱空間和事務日誌的本地文件系統上的路徑</description>
</property>

然後分發到其他節點,再重啓hdfs。

可以看到,現在配置的是兩個目錄,一個StorageType爲ARCHIVE、一個Storage爲DISK。

配置策略:

  • 創建目錄
hdfs dfs -mkdir -p /data/hdfs-test/data_phase/hot
hdfs dfs -mkdir -p /data/hdfs-test/data_phase/warm
hdfs dfs -mkdir -p /data/hdfs-test/data_phase/cold
  • 查看當前HDFS支持的存儲策略
[root@node1 Examples]# hdfs storagepolicies -listPolicies
Block Storage Policies:
BlockStoragePolicy{PROVIDED:1, storageTypes=[PROVIDED, DISK], creationFallbacks=[PROVIDED, DISK], replicationFallbacks=[PROVIDED, DISK]}
BlockStoragePolicy{COLD:2, storageTypes=[ARCHIVE], creationFallbacks=[], replicationFallbacks=[]}
BlockStoragePolicy{WARM:5, storageTypes=[DISK, ARCHIVE], creationFallbacks=[DISK, ARCHIVE], replicationFallbacks=[DISK, ARCHIVE]}
BlockStoragePolicy{HOT:7, storageTypes=[DISK], creationFallbacks=[], replicationFallbacks=[ARCHIVE]}
BlockStoragePolicy{ONE_SSD:10, storageTypes=[SSD, DISK], creationFallbacks=[SSD, DISK], replicationFallbacks=[SSD, DISK]}
BlockStoragePolicy{ALL_SSD:12, storageTypes=[SSD], creationFallbacks=[DISK], replicationFallbacks=[DISK]}
BlockStoragePolicy{LAZY_PERSIST:15, storageTypes=[RAM_DISK, DISK], creationFallbacks=[DISK], replicationFallbacks=[DISK]}
  • 分別設置三個目錄的存儲策略
hdfs storagepolicies -setStoragePolicy -path /data/hdfs-test/data_phase/hot -policy HOT
hdfs storagepolicies -setStoragePolicy -path /data/hdfs-test/data_phase/warm -policy WARM
hdfs storagepolicies -setStoragePolicy -path /data/hdfs-test/data_phase/cold -policy COLD
  • 查看三個目錄的存儲策略
hdfs storagepolicies -getStoragePolicy -path /data/hdfs-test/data_phase/hot
hdfs storagepolicies -getStoragePolicy -path /data/hdfs-test/data_phase/warm 
hdfs storagepolicies -getStoragePolicy -path /data/hdfs-test/data_phase/cold 
  • 測試
分別上傳文件
hdfs dfs -put /etc/profile /data/hdfs-test/data_phase/hot
hdfs dfs -put /etc/profile /data/hdfs-test/data_phase/warm
hdfs dfs -put /etc/profile /data/hdfs-test/data_phase/cold

查看不同存儲策略文件的block位置

hdfs fsck /data/hdfs-test/data_phase/hot/profile -files -blocks -locations

[root@node1 hadoop]# hdfs fsck /data/hdfs-test/data_phase/hot/profile -files -blocks -locations
Connecting to namenode via http://node1.itcast.cn:9870/fsck?ugi=root&files=1&blocks=1&locations=1&path=%2Fdata%2Fhdfs-test%2Fdata_phase%2Fhot%2Fprofile
FSCK started by root (auth:SIMPLE) from /192.168.88.100 for path /data/hdfs-test/data_phase/hot/profile at Sun Oct 11 22:03:05 CST 2020

/data/hdfs-test/data_phase/hot/profile 3158 bytes, replicated: replication=3, 1 block(s):  OK
0. BP-538037512-192.168.88.100-1600884040401:blk_1073742535_1750 len=3158 Live_repl=3  [DatanodeInfoWithStorage[192.168.88.101:9866,DS-96feb29a-5dfd-4692-81ea-9e7f100166fe,DISK], DatanodeInfoWithStorage[192.168.88.100:9866,DS-79739be9-5f9b-4f96-a005-aa5b507899f5,DISK], DatanodeInfoWithStorage[192.168.88.102:9866,DS-e28af2f2-21ae-4aa6-932e-e376dd04ddde,DISK]]

hdfs fsck /data/hdfs-test/data_phase/warm/profile -files -blocks -locations

/data/hdfs-test/data_phase/warm/profile 3158 bytes, replicated: replication=3, 1 block(s):  OK
0. BP-538037512-192.168.88.100-1600884040401:blk_1073742536_1751 len=3158 Live_repl=3  [DatanodeInfoWithStorage[192.168.88.102:9866,DS-636f34a0-682c-4d1b-b4ee-b4c34e857957,ARCHIVE], DatanodeInfoWithStorage[192.168.88.101:9866,DS-ff6970f8-43e0-431f-9041-fc440a44fdb0,ARCHIVE], DatanodeInfoWithStorage[192.168.88.100:9866,DS-79739be9-5f9b-4f96-a005-aa5b507899f5,DISK]]


hdfs fsck /data/hdfs-test/data_phase/cold/profile -files -blocks -locations
/data/hdfs-test/data_phase/cold/profile 3158 bytes, replicated: replication=3, 1 block(s):  OK
0. BP-538037512-192.168.88.100-1600884040401:blk_1073742537_1752 len=3158 Live_repl=3  [DatanodeInfoWithStorage[192.168.88.102:9866,DS-636f34a0-682c-4d1b-b4ee-b4c34e857957,ARCHIVE], DatanodeInfoWithStorage[192.168.88.101:9866,DS-ff6970f8-43e0-431f-9041-fc440a44fdb0,ARCHIVE], DatanodeInfoWithStorage[192.168.88.100:9866,DS-ca9759a0-f6f0-4b8b-af38-d96f603bca93,ARCHIVE]]

我們可以看到:

  • hot目錄中的block,3個block都在DISK磁盤

  • warm目錄中的block,1個block在DISK磁盤,另外兩個在archive磁盤

  • cold目錄中的block,3個block都在archive磁盤

參考:https://blog.csdn.net/androidlushangderen/article/details/51105876

2.7、內存存儲

介紹

  • HDFS支持寫入由DataNode管理的堆外內存

  • DataNode異步地將內存中數據刷新到磁盤,從而減少代價較高的磁盤IO操作,這種寫入稱之爲懶持久寫入

  • HDFS爲懶持久化寫做了較大的持久性保證。在將副本保存到磁盤之前,如果節點重新啓動,有非常小的機率會出現數據丟失。應用程序可以選擇使用懶持久化寫,以減少寫入延遲

該特性從ApacheHadoop 2.6.0開始支持。

適用場景

  • 比較適用於,當應用程序需要往HDFS中以低延遲的方式寫入相對較低數據量(從幾GB到十幾GB(取決於可用內存)的數據量時

  • 內存存儲適用於在集羣內運行,且運行的客戶端與HDFS DataNode處於同一節點的應用程序。使用內存存儲可以減少網絡傳輸的開銷

  • 如果內存不足或未配置,使用懶持久化寫入的應用程序將繼續工作,會繼續使用磁盤存儲。

配置

1、確定用於存儲在內存中的副本內存量

  • 在指定DataNode的hdfs-site.xml設置dfs.datanode.max.locked.memory ,這個參數和緩存共用
  • DataNode將確保懶持久化的內存不超過dfs.datanode.max.locked.memory
  • 例如,爲內存中的副本預留32 GB
<property>
      <name>dfs.datanode.max.locked.memory</name>
      <value>34359738368</value>
</property>

在設置此值時,請記住,還需要內存中的空間來處理其他事情,例如數據節點和應用程序JVM堆以及操作系統頁緩存。如果在與數據節點相同的節點上運行YARN節點管理器進程,則還需要YARN容器的內存

2、配置datanode

  • 在每個DataNode節點上初始化一個RAM磁盤

  • 通過選擇RAM磁盤,可以在DataNode進程重新啓動時保持更好的數據持久性

下面的設置可以在大多數Linux發行版上運行,目前不支持在其他平臺上使用RAM磁盤。

選擇tmpfs(VS ramfs)

  • Linux支持使用兩種類型的RAM磁盤-tmpfs和ramfs

  • tmpfs的大小受linux內核的限制,而ramfs可以使用所有系統可用的內存

  • tmpfs可以在內存不足情況下交換到磁盤上。但是,許多對性能要求很高的應用運行時都禁用內存磁盤交換

  • HDFS當前支持tmpfs分區,而對ramfs的支持正在開發中

掛載RAM磁盤

  • 使用Linux中的mount命令來掛載內存磁盤。例如:掛載32GB的tmpfs分區在/mnt/dn-tmpfs

sudo mount -t tmpfs -o size=32g tmpfs /mnt/dn-tmpfs/

  • 建議在/etc/fstab創建一個入口,在DataNode節點重新啓動時,將自動重新創建RAM磁盤

  • 另一個可選項是使用/dev/shm下面的子目錄。這是tmpfs默認在大多數Linux發行版上都可以安裝

  • 確保掛載的大小大於或等於dfs.datanode.max.locked.memory,或者寫入到/etc /fstab

  • 不建議使用多個tmpfs對懶持久化寫入的每個DataNode節點進行分區

設置RAM_DISK存儲類型tmpfs標籤

  • 標記tmpfs目錄中具有RAM_磁盤存儲類型的目錄

  • 在hdfs-site.xml中配置dfs.datanode.data.dir。例如,在具有三個硬盤卷的DataNode上,/grid /0, /grid /1以及 /grid /2和一個tmpfs掛載在 /mnt/dn-tmpfs, dfs.datanode.data.dir必須設置如下:

<property>
      <name>dfs.datanode.data.dir</name>
      <value>/grid/0,/grid/1,/grid/2,[RAM_DISK]/mnt/dn-tmpfs</value>
</property>
  • 這一步至關重要。如果沒有RAM_DISK標記,HDFS將把tmpfs卷作爲非易失性存儲,數據將不會保存到持久存儲,重新啓動節點時將丟失數據

其他配置

  • 確保啓用存儲策略:確保全局設置中的存儲策略是已啓用的。默認情況下,此設置是打開的

  • 使用內存存儲

  • 使用懶持久化存儲策略

  • 指定HDFS使用LAZY_PERSIST策略,可以對文件使用懶持久化寫入

可以通過以下三種方式之一進行設置:

  • 在目錄上設置㽾策略,將使其對目錄中的所有新文件生效

  • 這個HDFS存儲策略命令可以用於設置策略.

hdfs storagepolicies -setStoragePolicy -path <path> -policy LAZY_PERSIST #命令方式
 fs.setStoragePolicy(path, "LAZY_PERSIST"); //編程方式

三、副本放置策略

3.1、介紹

目前在HDFS中現有的副本放置策略類有2大繼承子類,分別爲BlockPlacementPolicyDefault, BlockPlacementPolicyWithNodeGroup,

最經典的3副本策略用的就是BlockPlacementPolicyDefault策略類.3副本如何存放在這個策略中得到了非常完美的實現.在BlockPlacementPolicyDefault類中的註釋具體解釋了3個副本的存放位置:

The  class is responsible for choosing the desired number of targets   for placing block replicas.   The replica placement strategy is that if  the writer is on a datanode,   the 1st replica is placed on the local  machine,    otherwise a random datanode. The 2nd replica  is placed on a datanode   that is on a different rack. The 3rd replica  is placed on a datanode   which is on a different node of the rack as  the second replica.  

簡要概況起來3點:

1st replica. 如果寫請求方所在機器是其中一個datanode,則直接存放在本地,否則隨機在集羣中選擇一個datanode.

2nd replica. 第二個副本存放於不同第一個副本的所在的機架.

3rd replica.第三個副本存放於第二個副本所在的機架,但是屬於不同的節點

3.2、BlockPlacementPolicyDefault

策略核心方法chooseTargets

在默認放置策略方法類中,核心方法就是chooseTargets,但是在這裏有2種同名實現方法,唯一的區別是有無favoredNodes參數.favoredNodes的意思是偏愛,喜愛的節點,只要分爲如下三個步驟:

  1. 初始化操作:計算每個機架所允許最大副本數,創建節點黑名單

  2. 選擇目標節點:將所選節點加入到結果列表中,同時加入到移除列表中,意爲已選擇過的節點

  3. 排序目標節點列表,形成pipeline

Pipeline節點的形成:整個過程就是傳入目標節點列表參數,經過getPipeline方法的處理,然後返回此pipeline.先來看getPipeline的註釋:

Return a pipeline of nodes. The pipeline is formed finding a shortest path that starts from the writer and traverses all nodes This is basically a traveling salesman problem.

關鍵是這句The pipeline is formed finding a shortest path that

starts from the writer,就是說從writer所在節點開始,總是尋找相對路徑最短的目標節點,最終形成pipeline,學習過算法的人應該知道,這其實也是經典的TSP旅行商問題

一句話概況來說,就是選出一個源節點,根據這個節點,遍歷當前可選的下一個目標節點,找出一個最短距離的節點,作爲下一輪選舉的源節點,這樣每2個節點之間的距離總是最近的,於是整個pipeline節點間的距離和就保證是足夠小的了.那麼現在另外一個問題還沒有解決,如何定義和計算2個節點直接的距離: 要計算其中的距離,我們首先要了解HDFS中如何定義節點間的距離,其中涉及到了拓撲邏輯結構的概念,結構圖如下:

這裏顯示的是一個三層結構的樹形效果圖,Root可以看出是一個大的集羣,下面劃分出了許多個機架,每個機架下面又有很多屬於此機架的節點.在每個連接點中,是通過交換機和路由器進行連接的.每個節點間的距離計算方式是通過尋找最近的公共祖先所需要的距離作爲最終的結果.比如Node1到Node2的距離是2,就是Node1->Rack1, Rack1->Node2.同理,Rack1的Node1到Rack2的Node1的距離就是4.

chooseTarget方法主邏輯:

final Node localNode = chooseTarget(numOfReplicas, writer, excludedNodes, blocksize, maxNodesPerRack, results, avoidStaleNodes, storagePolicy, EnumSet.noneOf(StorageType.class), results.isEmpty());

numOfReplicas, 額外需要複製的副本數

excludedNodes,移除節點集合,此集合內的節點不應被考慮作爲目標節點

results,當前已經選擇好的目標節點集合

storagePolicy,存儲類型選擇策略

首節點的選擇:

  1. 如果writer請求方本身位於集羣中的一個datanode之上,則第一個副本的位置就在本地節點上,很好理解,這樣直接就是本地寫操作了.

  2. 如果writer請求方純粹來源於外界客戶端的寫請求時,則從已選擇好的目標節點result列表中挑選第一個節點作爲首個節點.

  3. 如果result列表中還是沒有任何節點,則會從集羣中隨機挑選1個node作爲第一個localNode

經典的3副本存放位置,多餘的副本隨機存放的原理即可.當然在其間選擇的過程中可能會發生異常,因爲有的時候我們沒有配置機架感知,集羣中都屬於一個默認機架的default-rack,則會導致chooseRemoteRack的方法出錯,因爲沒有滿足條件的其餘機架,這時需要一些重試策略.

chooseLocalStorage,chooseLocalRack,chooseRemoteRack和chooseRandom方法,四個選擇目標節點位置的方法其實是一個優先級漸漸降低的方法,首先選擇本地存儲位置.如果沒有滿足條件的,再選擇本地機架的節點,如果還是沒有滿足條件的,進一步降級選擇不同機架的節點,最後隨機選擇集羣中的節點

目標節點存儲判斷好壞條件:

  1. storage的存儲類型是要求給定的存儲類型

  2. storage不能是READ_ONLY只讀的

  3. storage不能是壞的

  4. storage所在機器不應該是已下線或下線中的節點

  5. storage所在節點不應該是舊的,一段時間內沒有更新心跳的節點

  6. 節點內保證有足夠的剩餘空間能滿足寫Block要求的大小

  7. 要考慮節點的IO負載繁忙程度

  8. 要滿足同機架內最大副本數的限制

參考:https://blog.csdn.net/androidlushangderen/article/details/51178253

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