條紋單元:官方稱之爲Stripe Unit,我把它隱喻爲斑馬身上的黑白條紋,就稱每一個文件通過EC處理後的就是一個個的條紋單元。html
EC編碼奇偶校驗單元java
根據剩餘條紋單元和奇偶校驗單元恢復數據。node
一個具備6個塊,3副本會消耗6 x 3 = 18個塊存儲空間。而EC只須要 6個Block,再加上3個奇偶校驗,僅須要6 + 3 = 9個塊。節省了一半的存儲空間。算法
使用EC有幾個重要優點:shell
基於EC的文件存儲與Hadoop經典分塊存儲方式作了調整。apache
基於條紋的HDFS存儲邏輯上是由Block Group(塊組組成),每一個Block Group包含了必定數量的Internal Block(後續咱們稱爲EC Block)。若是一個文件有不少的EC Block,會佔用NameNode較大的內存空間。HDFS引入了新的分層Block命名協議,經過Block的ID能夠推斷出Block Group的ID,NameNode是基於Block Group而不是EC Block級別管理。緩存
客戶端讀取、寫入HDFS也作了調整,當以Online-EC寫入一個文件時,是以並行方式來處理Block Group中的Internal Block。網絡
DataNode上運行一個ErasureCodingWorker(ECWorker)任務,專門用於失敗的EC Block進行後臺數據恢復。一旦NameNode檢測到失敗的EC Block,NameNode會選擇一個DataNode進行數據恢復。架構
EC編解碼器是對EC Block上的條紋單元進行處理。編碼器將EC Block中的多個條紋單元做爲輸入,並輸出許多奇偶校驗單元。這個過程稱爲編碼。條紋單元和奇偶校驗單元稱爲EC編碼組。app
解碼的過程就是恢復數據的過程,能夠經過剩餘的條紋單元和奇偶校驗單元來恢復數據。
在比較不一樣的存儲方案時,須要考慮兩個重要因素:
HDFS中副本方案的容錯性爲:有N個副本,就能夠容忍N-1同時發生故障。存儲效率爲:1/N。
下面這張表格,是針對不一樣的存儲方案的數據容錯性和存儲效率。
能夠看出來,XOR只能容忍一個數據塊出現故障,而RS-6-三、RS-10-4容許3個、4個數據塊同時出現故障。但XOR的存儲效率是最高的、其次是RS-10-四、再下來是RS-6-3。而3副本的存儲效率是33%。
這張圖對比了連續存儲和條紋存儲方案在HDFS的示意圖。能夠明顯的看到,條紋存儲方案,將一個Block繼續分解爲一個個的條紋單元。並在一組DataNode的block中,循環寫入條紋單元。基於連續存儲或者條紋存儲,都是支持EC的。EC的方式存儲效率比較高,但增長了複雜度、以及較高消耗的故障恢復。條紋存儲方案比連續存儲更好的I/O吞吐量。但與傳統的MapReduce本地數據讀取相悖,由於數據都是跨網絡存儲的。讀取數據須要更多的網絡I/O開銷。
連續存儲
連續存儲容易實現,讀寫的方式與副本方式很是相似。但只有文件很大的場景適用。例如:使用RS-10-4,一個128M的文件仍然要寫入4個128M的就校驗塊。存儲開銷爲400%。這種方式,客戶端須要有GB級別的緩存來計算奇偶校驗單元。
條紋存儲
條紋存儲對小文件是友好的,能夠節省不少空間。條紋單元大小一般是(64KB或者1MB)。客戶端只須要有幾MB的緩存就能夠用於計算奇偶校驗單元。但這種方案,須要跨網絡I/O,性能會所以降低。要提高處理效率,須要將數據轉換爲連續存儲,但這就須要重寫整個文件了。
因此文件大小決定了使用哪一種方式更合適。Cloudera作了一些調研,發現其實HDFS中小文件(少於一個EC Block Group)的使用率佔整個集羣的36%-97%。小文件的處理更重要。因此HDFS EC使用的是條紋存儲的EC存儲方案。
爲了適應不一樣的業務需求,在HDFS中能夠針對文件、目錄配置不一樣的副本和EC策略。EC策略實現瞭如何對文件進行編碼/解碼方式。每一個策略包含如下屬性:
EC策略命名策略:EC編碼器-EC Block數量-奇偶校驗Block數量-條紋單元大小
。Hadoop中內置了5種策略:
同時,默認的副本策略也是支持的。副本策略設置在目錄上,這樣能夠前置目錄使用3副本方案,指定該目錄不繼承EC編碼策略。這樣,目錄中是能夠切換副本存儲方式的。
Replication存儲方式是始終啓用的,默認啓用的EC策略是:RS-6-3-1024K。與Replication存儲方式同樣,若是父目錄設置了EC策略,子文件/目錄會繼承父目錄的EC策略。
目錄級別的EC策略僅會影響在目錄中建立的新文件,這也意味着就的文件不會從新進行EC編碼,HDFS是使用online-EC,文件一旦建立,能夠查詢它的EC策略,但不能再更改
若是將已經進行EC編碼的文件移動到其餘EC策略的目錄,文件的EC編碼也不會改變。若是想要將文件轉換爲其餘的EC策略,須要重寫數據。能夠經過distcp來移動數據,而不是mv。
HDFS容許用戶基於XML本身來定義EC策略。例如:
<?xml version="1.0"?> <configuration> <!-- The version of EC policy XML file format, it must be an integer --> <layoutversion>1</layoutversion> <schemas> <!-- schema id is only used to reference internally in this document --> <schema id="XORk2m1"> <!-- The combination of codec, k, m and options as the schema ID, defines a unique schema, for example 'xor-2-1'. schema ID is case insensitive --> <!-- codec with this specific name should exist already in this system --> <codec>xor</codec> <k>2</k> <m>1</m> <options> </options> </schema> <schema id="RSk12m4"> <codec>RS</codec> <k>12</k> <m>4</m> <options> </options> </schema> <schema id="RS-legacyk12m4"> <codec>RS-legacy</codec> <k>12</k> <m>4</m> <options> </options> </schema> </schemas> <policies> <policy> <!-- the combination of schema ID and cellsize(in unit k) defines a unique policy, for example 'xor-2-1-256k', case insensitive --> <!-- schema is referred by its id --> <schema>XORk2m1</schema> <!-- cellsize must be an positive integer multiple of 1024(1k) --> <!-- maximum cellsize is defined by 'dfs.namenode.ec.policies.max.cellsize' property --> <cellsize>131072</cellsize> </policy> <policy> <schema>RS-legacyk12m4</schema> <cellsize>262144</cellsize> </policy> </policies> </configuration>
配置文件很容易理解,主要包含兩個部分組成:
RS-legacy:遺留的,基於純Java語言實現的EC編解碼器
而HDFS默認的RS和XOR編解碼器是基於Native實現的。
XOR算法
XOR(異或)算法是最簡單的EC實現,能夠從任意數量的數據生成1個奇偶校驗位。例如:1 ⊕ 0 ⊕ 1 ⊕ 1 = 1。但針對任意數量的條紋單元僅生成一個奇偶校驗位。HDFS中若是出現多個故障,這種恢復方式是不夠的。XOR的容錯能力爲1,存儲效率爲75%。
若是某一個X、Y對丟失,能夠經過奇偶檢驗位進行異或來恢復。
Reed-Solomon算法
RS算法克服了XOR算法的限制,基於線性代數運算來生成多個奇偶校驗位,能夠容忍多個失敗。RS 算法使用生成矩陣(GT,Generator Matrix)與 m 個數據單元相乘,以得到具備 m 個數據單元(data cells)和 n 個奇偶校驗單元(parity cells)的 extended codewords。RS算法的容錯能力最高爲n。存儲效率爲 m / m + n。例如:RS-6-3爲67%的存儲效率,而:RS-3-2爲60%的存儲效率。
上圖能夠看到,RS是使用複雜的線性代碼運算來生成多個奇偶校驗單元,能夠容忍每一個組出現多個故障。通常生產環境都是使用RS算法。RS-k-m是將k個條紋單元與生成矩陣Gt相乘,生成具備k個條紋單元和m個奇偶校驗單元。只要k + m個單元的k個可用,就能夠經過剩餘的條紋單元乘以Gt的倒數恢復存儲失敗。能夠容忍m個數據單元的故障。
默認,除了dfs.namenode.ec.system.default.policy
指定的默認策略,其餘的內置的EC策略都是禁用的。咱們能夠根據Hadoop集羣的大小、以及所需的容錯屬性,經過hdfs ec -enablePolicy -policy 策略名稱來啓用EC策略。例如:若是有5個節點的集羣,比較適合的就是RS-3-2-1024k,而RS-10-4-1024k策略就不合適了。
默認dfs.namenode.ec.system.default.policy爲RS-6-3-1024k。
# 讀取EC Block(條紋文件)的超時時間,默認5000毫秒 dfs.datanode.ec.reconstruction.stripedread.timeout.millis # 讀取EC Block的緩存大小,默認爲64KB dfs.datanode.ec.reconstruction.stripedread.buffer.size # 用於DataNode重建EC Block的線程數量,默認爲8個線程 dfs.datanode.ec.reconstruction.threads # EC後臺恢復任務數與複製Block的Xmits權重。NameNode基於這個Xmits值來調度任務到DataNode。默認爲0.5,設置爲0表示禁用EC恢復任務計算權重,始終都是1 Xmits。它的值爲:讀取正常EC Block的數量、以及暑輸出新的EC Block的最大值。例如:若是讀取6個正常的EC Block,輸出到兩個EC Block,則Xmits值爲:Max(6, 2) * 0.5 = 3。 dfs.datanode.ec.reconstruction.xmits.weight
EC相關的操做,使用hdfs ec
命令。
hdfs ec [generic options] [-setPolicy -path <path> [-policy <policyName>] [-replicate]] [-getPolicy -path <path>] [-unsetPolicy -path <path>] [-listPolicies] [-addPolicies -policyFile <file>] [-listCodecs] [-enablePolicy -policy <policyName>] [-disablePolicy -policy <policyName>] [-verifyClusterSetup -policy <policyName>...<policyName>] [-help [cmd ...]]
一、查看當前HDFS支持的ec策略
[root@node1 hadoop]# hdfs ec -listPolicies Erasure Coding Policies: ErasureCodingPolicy=[Name=RS-10-4-1024k, Schema=[ECSchema=[Codec=rs, numDataUnits=10, numParityUnits=4]], CellSize=1048576, Id=5], State=DISABLED ErasureCodingPolicy=[Name=RS-3-2-1024k, Schema=[ECSchema=[Codec=rs, numDataUnits=3, numParityUnits=2]], CellSize=1048576, Id=2], State=DISABLED ErasureCodingPolicy=[Name=RS-6-3-1024k, Schema=[ECSchema=[Codec=rs, numDataUnits=6, numParityUnits=3]], CellSize=1048576, Id=1], State=ENABLED ErasureCodingPolicy=[Name=RS-LEGACY-6-3-1024k, Schema=[ECSchema=[Codec=rs-legacy, numDataUnits=6, numParityUnits=3]], CellSize=1048576, Id=3], State=DISABLED ErasureCodingPolicy=[Name=XOR-2-1-1024k, Schema=[ECSchema=[Codec=xor, numDataUnits=2, numParityUnits=1]], CellSize=1048576, Id=4], State=ENABLED
咱們看到目前個人HDFS集羣上面啓用了兩個策略:一個是RS-6-3-1024k、一個是XOR-2-1-1024k。
二、查看當前HDFS支持的編解碼器
[root@node1 hadoop]# hdfs ec -listCodecs Erasure Coding Codecs: Codec [Coder List] RS [RS_NATIVE, RS_JAVA] RS-LEGACY [RS-LEGACY_JAVA] XOR [XOR_NATIVE, XOR_JAVA]
三、設置EC編碼策略。由於個人測試集羣只有3個節點,因此只能使用XOR-2-1-1024k。先要將XOR-2-1-1024k啓用。
-- 建立用於存放冷數據的目錄 [root@node1 hadoop]# hdfs dfs -mkdir -p /workspace/feng/cold_data -- 啓用XOR-2-1-1024 EC策略 [root@node1 hadoop]# hdfs ec -enablePolicy -policy XOR-2-1-1024k Erasure coding policy XOR-2-1-1024k is enabled -- 驗證當前集羣是否支持全部啓用的或者指定的EC策略(這個命令應該是3.2.x添加的,我當前是3.1.4,還不支持這個命令) -- hdfs ec -verifyClusterSetup -policy XOR-2-1-1024k -- 設置冷數據EC存儲策略 [root@node1 hadoop]# hdfs ec -setPolicy -path /workspace/feng/cold_data -policy XOR-2-1-1024k Set XOR-2-1-1024k erasure coding policy on /workspace/feng/cold_data -- 查看冷數據目錄的存儲策略 [root@node1 hadoop]# hdfs ec -getPolicy -path /workspace/feng/cold_data XOR-2-1-1024k
[root@node1 software]# hdfs dfs -put hadoop-3.1.4.tar.gz /workspace/feng/cold_data 2021-01-16 14:23:28,681 WARN erasurecode.ErasureCodeNative: ISA-L support is not available in your platform... using builtin-java codec where applicable
此處,Hadoop警告提示,當前個人操做系統平臺,不支持ISA-L,默認RS、XOR使用的是Native方式進行編解碼,會基於Intel的ISA-L加速編解碼。
咱們來查看下HDFS文件的Block的信息:
[root@node3 subdir2]# hdfs fsck /workspace/feng/cold_data/hadoop-3.1.4.tar.gz -files -blocks
咱們看到文件是以XOR-2-1-1024k進行EC編碼,而且有兩個Block。總共有兩個EC Block Group。
0. BP-538037512-192.168.88.100-1600884040401:blk_-9223372036854775232_2020 len=268435456 Live_repl=3 1. BP-538037512-192.168.88.100-1600884040401:blk_-9223372036854775216_2021 len=38145321 Live_repl=3
總共的EC Block Group = 306580777字節,與原始的數據文件相等。
Erasure Coded Block Groups: Total size: 306580777 B Total files: 1 Total block groups (validated): 2 (avg. block group size 153290388 B) Minimally erasure-coded block groups: 2 (100.0 %) Over-erasure-coded block groups: 0 (0.0 %) Under-erasure-coded block groups: 0 (0.0 %) Unsatisfactory placement block groups: 0 (0.0 %) Average block group size: 3.0 Missing block groups: 0 Corrupt block groups: 0 Missing internal blocks: 0 (0.0 %) FSCK ended at Sat Jan 16 16:59:46 CST 2021 in 1 milliseconds
原始文件大小:
[root@node1 software]# ll hadoop-3.1.4.tar.gz -rw-r--r-- 1 root root 306580777 Sep 25 09:29 hadoop-3.1.4.tar.gz
咱們能夠觀察看到當前的Block Group大小爲:256MB。而個人HDFS集羣配置的dfs block size是:128MB。
<property> <name>dfs.blocksize</name> <value>134217728</value> <final>false</final> <source>hdfs-default.xml</source> </property>
由於當前的Block size是128MB,而EC的策略是:XOR-2-1,也就是一個Block Group 2個Block,因此Block Group的大小就是256MB了。
假設如今須要將一個3副本存儲方式的文件,遷移到配置了EC策略的目錄中。
-- 建立一個用於測試的數據目錄 hdfs dfs -mkdir /workspace/feng/test_data -- 上傳一個測試文件 hdfs dfs -put hbase-logs.zip /workspace/feng/test_data -- 啓動YARN start-yarn.sh -- 使用distcp移動到EC策略的目錄中(此處要跳過檢驗和,由於使用EC編碼確定校驗失敗) hadoop distcp -update -skipcrccheck /workspace/feng/test_data/hbase-logs.zip /workspace/feng/cold_data
能夠對比下該文件的block數據:
3副本方式文件
[root@node1 hadoop]# hdfs fsck /workspace/feng/test_data/hbase-logs.zip -files -blocks Connecting to namenode via http://node1:9870/fsck?ugi=root&files=1&blocks=1&path=%2Fworkspace%2Ffeng%2Ftest_data%2Fhbase-logs.zip FSCK started by root (auth:SIMPLE) from /192.168.88.100 for path /workspace/feng/test_data/hbase-logs.zip at Sat Jan 16 19:43:39 CST 2021 /workspace/feng/test_data/hbase-logs.zip 6970734 bytes, replicated: replication=3, 1 block(s): OK 0. BP-538037512-192.168.88.100-1600884040401:blk_1073742800_2023 len=6970734 Live_repl=3 Status: HEALTHY Number of data-nodes: 3 Number of racks: 1 Total dirs: 0 Total symlinks: 0 Replicated Blocks: Total size: 6970734 B Total files: 1 Total blocks (validated): 1 (avg. block size 6970734 B) Minimally replicated blocks: 1 (100.0 %) Over-replicated blocks: 0 (0.0 %) Under-replicated blocks: 0 (0.0 %) Mis-replicated blocks: 0 (0.0 %) Default replication factor: 3 Average block replication: 3.0 Missing blocks: 0 Corrupt blocks: 0 Missing replicas: 0 (0.0 %) Erasure Coded Block Groups: Total size: 0 B Total files: 0 Total block groups (validated): 0 Minimally erasure-coded block groups: 0 Over-erasure-coded block groups: 0 Under-erasure-coded block groups: 0 Unsatisfactory placement block groups: 0 Average block group size: 0.0 Missing block groups: 0 Corrupt block groups: 0 Missing internal blocks: 0 FSCK ended at Sat Jan 16 19:43:39 CST 2021 in 1 milliseconds The filesystem under path '/workspace/feng/test_data/hbase-logs.zip' is HEALTHY
EC編碼後的文件
[root@node1 hadoop]# hdfs fsck /workspace/feng/cold_data/hbase-logs.zip -files -blocks Connecting to namenode via http://node1:9870/fsck?ugi=root&files=1&blocks=1&path=%2Fworkspace%2Ffeng%2Fcold_data%2Fhbase-logs.zip FSCK started by root (auth:SIMPLE) from /192.168.88.100 for path /workspace/feng/cold_data/hbase-logs.zip at Sat Jan 16 19:42:51 CST 2021 /workspace/feng/cold_data/hbase-logs.zip 6970734 bytes, erasure-coded: policy=XOR-2-1-1024k, 1 block(s): OK 0. BP-538037512-192.168.88.100-1600884040401:blk_-9223372036854774560_2128 len=6970734 Live_repl=3 Status: HEALTHY Number of data-nodes: 3 Number of racks: 1 Total dirs: 0 Total symlinks: 0 Replicated Blocks: Total size: 0 B Total files: 0 Total blocks (validated): 0 Minimally replicated blocks: 0 Over-replicated blocks: 0 Under-replicated blocks: 0 Mis-replicated blocks: 0 Default replication factor: 3 Average block replication: 0.0 Missing blocks: 0 Corrupt blocks: 0 Missing replicas: 0 Erasure Coded Block Groups: Total size: 6970734 B Total files: 1 Total block groups (validated): 1 (avg. block group size 6970734 B) Minimally erasure-coded block groups: 1 (100.0 %) Over-erasure-coded block groups: 0 (0.0 %) Under-erasure-coded block groups: 0 (0.0 %) Unsatisfactory placement block groups: 0 (0.0 %) Average block group size: 3.0 Missing block groups: 0 Corrupt block groups: 0 Missing internal blocks: 0 (0.0 %) FSCK ended at Sat Jan 16 19:42:51 CST 2021 in 1 milliseconds
基於副本冗餘方式和EC方式共存。
參考文獻: