---持續更新中,可留言討論---
--題目導航見頁面左上角的懸浮框#目錄導航#--
一、目錄:
- 集群規划
- HDFS HA
- 冒煙測試
- 功能特性
二、集群規划:
- 負載類型
- 容量規划
- 可擴展性
- 角色分離
- 管理節點
- Master節點
- Worker節點
- 邊緣節點
三、HDFS HA(高可用)
架構原理見下圖:
四、冒煙測試:
詳細說明參見之前的博客:https://www.cnblogs.com/huxinga/p/9627084.html
五、功能特性:
- HDFS Balancer
- 快照 Snapshots
- 配額 Quota
- 權限 ACLs
- 存儲策略
- 集中緩存管理
- 機架感知
- Erasure Coding
- Memory as Storage
- Short-Circuit Local Reads
5.1 HDFS Balancer
balancer是當hdfs集群中一些datanodes的存儲要寫滿了或者有空白的新節點加入集群時,用於均衡hdfs集群磁盤使用量的一個工具。
Hadoop的HDFS集群非常容易出現機器與機器之間磁盤利用率不平衡的情況,比如集群中添加新的數據節點。當HDFS出現不平衡狀況的時候,將引發很多問題,比如MR程序無法很好地利用本地計算的優勢,機器之間無法達到更好的網絡帶寬使用率,機器磁盤無法利用等等。可見,保證HDFS中的數據平衡是非常重要的。在Hadoop中,包含一個Balancer程序,通過運行這個程序,可以使得HDFS集群達到一個平衡的狀態
參考命令:
hdfs balancer hdfs dfsadmin [-setBalancerBandwidth <bandwidth in bytes per second>]
<property>
<name>dfs.datanode.balance.bandwidthPerSec</name>
<value>6250000</value>
</property>

5.2 快照 snapshots
HDFS快照是文件系統的只讀時間點的副本。可以在文件系統的子樹或整個文件系統上拍攝快照。快照的一些常見⽤例是數據備份,防⽌用戶錯誤和災難恢復。
HDFS中可以對目錄創建Snapshot,創建之后不管后續目錄發生什么變化,都可以通過snapshot找回原來的文件和目錄結構。
實現原理:
實現上是通過在每個目標節點下面創建snapshot節點,后續任何子節點的變化都會同步記錄到snapshot上。例如刪除子節點下面的文件,並不是直接文件元信息以及數據刪除,而是將他們移動到snapshot下面。這樣后續還能夠恢復回來。另外snapshot保存是一個完全的現場,不僅是刪除的文件還能找到,新創建的文件也無法看到。后一種效果的實現是通過在snapshot中記錄哪些文件是新創建的,查看列表的時候將這些文件排除在外。
參考命令:
# 為指定目錄開啟快照功能 hdfs dfsadmin -allowSnapshot <path> # 列出開啟了快照功能的目錄 hdfs lsSnapshottableDir # 創建快照 hdfs dfs -createSnapshot <path> [<snapshotName>] # ⽐較兩個快照之間的區別 hdfs snapshotDiff <path> <fromSnapshot> <toSnapshot> # 列出快照內的⽂文件 hdfs dfs -ls /foo/.snapshot # 從快照中恢復數據。 此處使用了了preserve選項來保留時間戳、所有權、權限、ACL 和 XAttrs擴展屬性 hdfs dfs -cp -ptopax /foo/.snapshot/s0/bar /tmp
例子分析:
我們通過一個例子來分析整個snapshot的實現細節:
1. 文件目錄樹如下圖所示,並且我們已經通過命令啟動了a的snapshot功能,結構如下圖所示:

圖中.snapshot是虛擬節點,保存了所有的snapshot列表,其中diff中還保存當前節點下面的變化,一個snapshot對應於一個diff.要注意的是snapshot中可以被多個目錄的diff引用,后續會進行說明。
2. 當我們執行createSnapshot命令時,結果如下:
3. 當刪除文件e的時候
不論是刪除一個文件還是一個目錄,只要是直接子節點,都會將節點轉換為快照版本.例如e會變成INodeFileWithSnapshot,在a的DirectoryDiff中ChildDiff中deleted列表中將會包含e,而在a的正常節點下會被刪除。目錄節點的處理同樣。
4. 刪除孫子節點是的情況
處理這種節點的原則是:先將孫子節點轉變為Snapshot版本,然后將父節點變為snapshot版本,同時將孫子節點版本加入到直接父節點的diff列表中。為了能夠通過同一個snapshot找到當時的文件,需要將新的diff指向到老的snapshot版本上。圖中d節點是INodeDirectoryWithSnapshot(不是INodeDiretorySnapshottable, 本身不允許在d上創建snapshot)
5.3 配額 Quata
Name Quotas :
Name Quota 是該目錄下所有文件和目錄總的數量的硬限制。如果超出配額,文件和目錄創建將失敗。配額為1會強制目錄保持為空。 重命名后依然有效
Space Quotas :
Space Quota 是該目錄下所有文件使用的字節數的硬限制。如果配額不允許寫入完整塊,則塊分配將失敗。塊的每個副本都會計入配額。 最好設置空間大小為快的整數倍。空間配額為0時可以創建文件,但不能向文件中寫入內容,單位為BYTE。
存儲類型配額 :
存儲類型配額是該目錄中文件使用特定存儲類型(SSD,DISK,ARCHIVE)的硬限制
參考命令:
hdfs dfsadmin -setQuota <N> <directory>...<directory> hdfs dfsadmin -clrQuota <directory>...<directory> hdfs dfsadmin -setSpaceQuota <N> <directory>...<directory> hdfs dfsadmin -clrSpaceQuota <directory>...<directory> hdfs dfsadmin -setSpaceQuota <N> -storageType <storagetype> <directory>...<directory> hdfs dfsadmin -clrSpaceQuota -storageType <storagetype> <directory>...<directory> hadoop fs -count -q [-h] [-v] [-t [comma-separated list of storagetypes]] <directory>...<directory
5.4 HDFS ACLs
ACLs主要是給指定的用指定目錄分配指定的權限
首先需要了解chmod命令詳情,參考我之前的博客:https://www.cnblogs.com/huxinga/p/9946464.html
HDFS支持POSIX ACL(訪問控制列表),啟用HDFS ACLs:
dfs.namenode.acls.enabled = true
參考命令:
hdfs dfs [generic options] -setfacl [-R] [{-b|-k} {-m|-x <acl_spec>} <path>] hdfs dfs [generic options] –setfacl --set <acl_spec> <path> hdfs dfs [generic options] -getfacl [-R] <path>
5.5 存儲策略
存儲類型:
- DISK-普通磁盤,存儲
- SSD -SSD盤
- RAM_DISK 內存盤
- ARCHIVE -歸檔/壓縮,不是實際的磁盤類型,而是數據被壓縮存儲。
存儲策略:
- Hot - 存儲和計算都熱。 如果是熱快,那么復制的目標也是DISK(普通的磁盤)。
- Cold -用於有限計算的存儲。 數據不再使用,或者需要歸檔的數據被移動到冷存儲。如果數據塊是冷的,則復制使用ARCHIVE.
- Warm -半冷半熱。warm塊的復制內容,部分放置在DISK,其它的在ARCHIVE.
- All_SSD - 所有數據存儲在SSD.
- One_SSD - 一個復制在SSD,其它的在DISK.
- Lazy_Persist -只針對只有一個復制的數據塊,它們被放在RAM_DISK,之后會被寫入DISK。
當有足夠空間的時候,塊復制使用下表中第三列所列出的存儲類型。
如果第三列的空間不夠,則考慮用第四列的(創建的時候)或者第五列的(復制的時候)
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 | <none> | ARCHIVE |
5 | Warm | DISK: 1, ARCHIVE: n-1 | ARCHIVE, DISK | ARCHIVE, DISK |
2 | Cold | ARCHIVE: n | <none> | <none> |
LAZY_PERSIST策略只用於復制一個塊
文件/路徑的存儲策略按照如下規則解析:
-
如果有設定特定的策略,那么就是那個策略
-
如果沒有設定,就返回上級目錄的存儲策略。如果是沒有策略的根目錄,那么返回默認的存儲策略(hot-編號7的)。
HDFS MOVER-一個新的數據遷移工具:
這個工具用戶歸檔數據,它類似於Balancer(移動數據方面)。MOVER定期掃描HDFS文件,檢查文件的存放是否符合它自身的存儲策略。如果數據塊不符合自己的策略,它會把數據移動到該去的地方。
語法
hdfs mover [-p <files/dirs> | -f <local file name>]
-p 指定要遷移的文件/目錄,多個以空格分隔
-f 指定本地一個文件路徑,該文件列出了需要遷移的文件或者目錄(一個一行)
如果不指定參數,那么就移動根目錄
參考命令:
列出所有存儲策略:
hdfs storagepolicies -listPolicies
設置存儲策略:
hdfs storagepolicies -setStoragePolicy -path <path> -policy <policy>
取消存儲策略:
hdfs storagepolicies -unsetStoragePolicy -path <path>
獲取存儲策略:
hdfs storagepolicies -getStoragePolicy -path <path>
5.6 集中式緩存管理
概念:
第一層是緩存,即為存儲在HDFS中文件提供緩存的機制,從而可以加速DFSClient對文件的讀操作;
第二層概念是集中式的管理,傳統的HDFS緩存依賴了OS本身的緩存機制,但是這種緩存機制不能被管理員或中央節點進行管理,不能自由的控制哪些文件緩存,哪些文件不進行緩存;集中式的管理可以提高了對緩存內存的可控性
原理架構:
1、User通過api入口與NN進行交互,告訴NN緩存哪些文件,或者取消對那些文件的緩存;
2、NN中維護了緩存path列表;在每次接受到User的緩存請求時候,把請求的Path轉化為一系列的Blocks,並把這些Blocks加入到一個待cache的隊列中
3、在DN中緩存的真實內容是Blocks,在DN每次心跳協議與NN進行交互時候,NN會把屬於該DN的緩存的Blocks放在心跳協議的返回值中返回給DN,DN進行緩存中
4、同時DN維持一個NN之間類似心跳協議的定時協議,定時同步DN中緩存Block的狀態;
5、DFSClient在讀取緩存中的文件Blocks時,可以直接從Cache中讀取;
HDFS集中緩存兩個主要概念:Cache Directive和Cahce Pool
1、Cache Directive:一個directive是一個緩存的path,它可以是目錄,也可以是文件;注意:目錄的緩存是非遞歸的,只緩存目錄內第一層的文件,不會緩存目錄中目錄;一個Directive有一個參數replication,表示該path的緩存的副本數;注意,可以對一個文件進行多次緩存;一個Directive有一個參數expiration,可以控制緩存的TTL(time-to-live),目前該時間為絕對時間,可以表示為分鍾,小時和天數,比如 -ttl 30m, 4h, 2d。 測試顯示一個cache過期了,NN不會自動將它從緩存列表中刪除,只是在不再反饋給DFSClient進行讀操作,cache的內存是否會自動釋放,待測試; 測試結果表示不會釋放內存,所以過期的cache,還是需要手動的去刪除它;
2、Cache Pool:是Cache的管理單元,每個Pool擁有與Unix相似的權限,同時Pool也有quota limit限制(磁盤使用情況和限額)。
配置:
<property>
<name>dfs.datanode.max.locked.memory</name>
<value>268435456</value>
</property>
必須配置,單位為byte,默認該值為0,從描述中可以看到。如果該值為0,相當於關閉了集中緩存的功能;
參考命令:
hdfs cacheadmin -addPool <name> [-owner <owner>] [-group <group>] [-mode <mode>] [-limit <limit>] [-maxTtl <maxTtl>] hdfs cacheadmin -addDirective -path <path> -pool <pool-name> [-force] [-replication <replication>] [-ttl <time-to-live>]
1、Pool控制:可以通過"hdfs cacheadmin -addPool"創建一個pool,“hdfs cacheadmin -modifyPool”刪除一個pool,"hdfs cacheadmin -removePool"刪除一個pool,“ hdfs cacheadmin -removePool”刪除一個pool。
2、Directive控制:集中緩存中一個文件是否會被緩存,完全用管理員來控制,管理員可以通過" hdfs cacheadmin -addDirective"來添加緩存,該命令會返回一個緩存id;“hdfs cacheadmin -removeDirective”通過該命令來刪除指定緩存id的緩存;“ hdfs cacheadmin -removeDirectives”通過該命令來刪除指定緩存path的緩存,該命令可以一次刪除多個緩存;“hdfs cacheadmin -listDirectives”顯示當前所有的緩存;詳細的參數,在命令行中輸入 hdfs cacheadmin可以看得到;
或者參考:http://hadoop.apache.org/docs/r2.3.0/hadoop-project-dist/hadoop-hdfs/CentralizedCacheManagement.html 官方文檔 。
5.7 機架感知
Hadoop在設計時考慮到數據的安全,數據文件默認在HDFS上存放三份。顯然,這三份副本肯定不能存儲在同一個服務器節點。那怎么樣的存儲策略能保證數據既安全也能保證數據的存取高效呢?
HDFS分布式文件系統的內部有一個副本存放策略:以默認的副本數=3為例:
1、第一個副本塊存本機
2、第二個副本塊存跟本機同機架內的其他服務器節點
3、第三個副本塊存不同機架的一個服務器節點上
好處:
1、如果本機數據損壞或者丟失,那么客戶端可以從同機架的相鄰節點獲取數據,速度肯定要比跨機架獲取數據要快。
2、如果本機所在的機架出現問題,那么之前在存儲的時候沒有把所有副本都放在一個機架內,這就能保證數據的安全性,此種情況出現,就能保證客戶端也能取到數據
HDFS為了降低整體的網絡帶寬消耗和數據讀取延時,HDFS集群一定會讓客戶端盡量去讀取近的副本,那么按照以上面解釋的副本存放策略的結果:
1、如果在本機有數據,那么直接讀取
2、如果在跟本機同機架的服務器節點中有該數據塊,則直接讀取
3、如果該HDFS集群跨多個數據中心,那么客戶端也一定會優先讀取本數據中心的數據
機架感知就是使HDFS確定兩個節點是否是統一節點以及確定的不同服務器跟客戶端的遠近。
在默認情況下,HDFS集群是沒有機架感知的,也就是說所有服務器節點在同一個默認機架中。那也就意味着客戶端在上傳數據的時候,HDFS集群是隨機挑選服務器節點來存儲數據塊的三個副本的。
那么假如默認情況下的HDFS集群,datanode1和datanode3在同一個機架rack1,而datanode2在第二個機架rack2,那么客戶端上傳一個數據塊block_001,HDFS將第一個副本存放在dfatanode1,第二個副本存放在datanode2,那么數據的傳輸已經跨機架一次(從rack1到rack2),然后HDFS把第三個副本存datanode3,此時數據的傳輸再跨機架一次(從rack2到rack1)。顯然,當HDFS需要處理的數據量比較大的時候,那么沒有配置機架感知就會造成整個集群的網絡帶寬的消耗非常嚴重。
1、增加datanode節點
增加datanode節點,不需要重啟namenode
非常簡單的做法:在topology.data文件中加入新加datanode的信息,然后啟動起來就OK
2、節點間距離計算
有了機架感知,NameNode就可以畫出下圖所示的datanode網絡拓撲圖。D1,R1都是交換機,最底層是datanode。則H1的rackid=/D1/R1/H1,H1的parent是R1,R1的是D1。這些rackid信息可以通過topology.script.file.name配置。有了這些rackid信息就可以計算出任意兩台datanode之間的距離,得到最優的存放策略,優化整個集群的網絡帶寬均衡以及數據最優分配。
distance(/D1/R1/H1,/D1/R1/H1)=0 相同的datanode distance(/D1/R1/H1,/D1/R1/H2)=2 同一rack下的不同datanode distance(/D1/R1/H1,/D1/R2/H4)=4 同一IDC下的不同datanode distance(/D1/R1/H1,/D2/R3/H7)=6 不同IDC下的datanode
參考命令:
<property> <name>net.topology.script.file.name</name> <value>/etc/hadoop/conf/rack-topology.sh</value> </property>
5.8 Erasure Coding
減少數據存儲資源的使用,同時保證節點級、機架級容錯
- RS算法,默認為RS(6,3),需⾄少9個節點、9個機架才能同時滿足節點級、機架級容錯
- 條帶化
優點:
- 客戶端緩存數據較少
- 無論文件大小都適用
缺點: - 會影響一些位置敏感任務的性能,因為原先在一個節點上的塊被分散到了多個不同的節點上
- 和多副本存儲策略轉換比較麻煩
通常情況下,HDFS多備份機制存儲數據,一個塊是128M,加上備份,一起是128M*3,允許同時丟失2個數據塊。
優點:
- 容易實現
- 方便和多副本存儲策略進行轉換
缺點:
- 需要客戶端緩存足夠的數據塊
- 不適合存儲小文件
而采用EC的情況下,默認是RS(6,3),就是說將一個塊128M的數據分為6份,每份大概21M,以條帶化的形式存儲到6個數據節點上,同時通過RS算法生成3個校驗數據。EC就是這9個數據允許丟失3及以下的情況下還能保證數據的完整恢復。圖片以RS(3,2)舉例。
EC的優點是提高了空間利用率,通常采用的HDFS多備份機制每個塊一共需要128M*3的空間(允許丟失2塊),而EC僅需要21M*6+21M*3的空間(21M*3為生成的3個校驗數據所占的空間)
說到這里我想到:1 .EC是以時間換空間的技術,所有的存儲技術不是時間換空間,就是空間換時間 2. 計算HDFS多備份機制最少保留的數據量為128M*3*1/3=128M,而采用EC機制最少保留的數據量為(128+64)*2/3 =128M,所以說無論是什么數據存儲技術,允許丟失的數據量=總數據-原數據
我怎么這么厲害!!
參考代碼:
hdfs erasurecode [generic options] [-setPolicy [-p <policyName>] <path>] [-getPolicy <path>] [-listPolicies]
5.9 Memory as Storage:
HDFS支持寫入由數據節點管理的堆外內存。數據節點將異步刷新內存中的數據到磁盤,從而從性能敏感的IO路徑中刪除昂貴的磁盤IO和校驗和計算,因此我們將這種寫入稱為Lazy Persist。 HDFS為Lazy Persist Writes提供盡力而為的持久性保證。在將副本持久保存到磁盤之前,如果節點重新啟動,則可能會丟失數據。應用程序可以選擇使用Lazy Persist Writes來換取一些持久性保證,以減少延遲。
換一個通俗的解釋,好比我有個內存數據塊隊列,在隊列頭部不斷有新增的數據塊插入,就是待存儲的塊,因為資源有限 ,我要把隊列尾部的塊,也就是早些時間點的塊持久化到磁盤中,然后才有空間騰出來存新的塊.然后形成這樣的一個循環,新的塊加入,老的塊移除,保證了整體數據的更新.
HDFS的LAZY_PERSIST內存存儲策略架構原理如下圖所示:
1,對目標文件目錄設置StoragePolicy為LAZY_PERSIST的內存存儲策略。
2,客戶端進程向NameNode發起創建/寫文件的請求。
3,然后將數據寫入具體的DataNode。
4,DataNode將數據寫入RAM內存中。
5,啟動異步線程服務將數據持久化到磁盤中。
內存的異步持久化存儲,就是明顯不同於其他介質存儲數據的地方.這應該也是LAZY_PERSIST的名稱的源由吧,數據不是馬上落盤,而是”lazy persisit”懶惰的方式,延時的處理.
參考命令:
1、設置內存值,此值與MemoryStorage共享,且必須⼩小於/etc/security/limits.conf中的配置值
dfs.datanode.max.locked.memory
2、掛載MEM磁盤,並寫⼊入/etc/fstab中
$ sudo mount -t tmpfs -o size=32g tmpfs /mnt/dn-tmpfs/
3、為MEM磁盤添加標簽:RAM_DISK
dfs.datanode.data.dir = [RAM_DISK]/mnt/dn-tmpfs
4、設置存儲策略略
$ hdfs storagepolicies -setStoragePolicy -path <path> -policy LAZY_PERSIST
5.10 Short-Circuit Local Reads
基於Hadoop的一大原則:移動計算比移動數據的開銷小。在HDFS中,讀取通常通過DataNode。因此,當客戶端要求DataNode讀取文件時,DataNode從磁盤讀取該文件並通過TCP套接字將數據發送到客戶端。所謂的“短路”讀取繞過DataNode,允許客戶端直接讀取文件。顯然,這只有在客戶端與數據位於同一位置的情況下才有可能。短路讀取為許多應用提供了顯着的性能提升。
解決:讀取數據的客戶端DFSclient和提供數據的DataNode在同一節點的情況下,繞開DN自己去讀數據,可以提升性能。
參考命令:
dfs.client.read.shortcircuit = true dfs.domain.socket.path = /var/lib/hadoop-hdfs/dn_socket