1.目的
????副本是昂貴的--在HDFS中默認(rèn)的3副本機(jī)制有200%的存儲空間和其它的資源(比如:網(wǎng)絡(luò)帶寬)開銷。然而,相對于低 I/O 活動的暖數(shù)據(jù)集和冷數(shù)據(jù)集,在正常的操作期間對其額外的副本很少訪問,但是仍然消耗與第一副本相同數(shù)量的資源。
????因此,一個自然的改進(jìn)是使用糾刪碼(Erasure Coding)替代副本機(jī)制,它使用更少的存儲空間提供相同的容錯級別,一個典型的糾刪碼設(shè)置,會使得存儲空間的開銷不超過50%;一個EC文件的副本因子是無意義的,它一直保持為1,并且不能通過命令 -setrep修改EC的副本因子的值。
2.背景
????磁盤陣列(RAID)是在存儲系統(tǒng)中,使用EC最出名的。RAID使用條帶的方式實(shí)現(xiàn)的EC,它提供邏輯上序列的數(shù)據(jù)(比如文件)到更小的單元(比如比特、字節(jié)、或塊),并存儲連續(xù)的單元到不同的磁盤上。在本指南的其余部分,這種條帶分布單元被稱為條帶單元(或者單元),對于每一個條帶原始數(shù)據(jù)單元,計(jì)算并存儲一定數(shù)量的奇偶校驗(yàn)單元,這個過程叫做編碼。通過對剩余的數(shù)據(jù)和奇偶校驗(yàn)單元解碼計(jì)算,可以恢復(fù)任意條帶單元的錯誤。
????將EC和HDFS集成可以提高存儲效率,然而同樣提供傳統(tǒng)的基于副本機(jī)制的HDFS持久化部署,例如:3副本的文件有6個塊,將會消耗 6*3 = 18個塊的磁盤空間,但是使用EC(6個數(shù)據(jù),3個校驗(yàn))部署,他將只消耗9個塊的磁盤空間。
3.框架
????在EC的環(huán)境中,條帶有若干主要的優(yōu)點(diǎn),首先,它能在線EC(使用EC的格式直接寫數(shù)據(jù)),避免轉(zhuǎn)換階段,直接節(jié)省存儲空間。在線EC通過并行利用多磁盤主軸增強(qiáng)I/O性能;這在高性能的網(wǎng)絡(luò)的集群中尤其需要。其次,它自然的分發(fā)小文件到多個DataNodes,消除了將多個文件綁定到一個編碼組的需要,這會很大的簡化文件的操作,比如刪除、配額匯報(bào)和在聯(lián)邦集群中不同的Namespace之間遷移數(shù)據(jù)等。在典型的HDFS集群中,小文件占總存儲空間3/4以上的消耗,為了更好的支持小文件,在第一階段工作中,HDFS支持條帶的EC。在未來,HDFS也會支持連續(xù)的EC布局,查看設(shè)計(jì)文檔,更多的信息在issue HDFS-7285中討論。
3.1.NameNode擴(kuò)展
? ??條帶的HDFS文件是由邏輯上的塊組構(gòu)成,每個塊組包含一定數(shù)量的內(nèi)部塊,為了減少額外的塊對NameNode內(nèi)存消耗,提出了新的分層塊命名協(xié)議,塊組的ID可以從它的內(nèi)部塊的任意ID中推斷出來,這允許塊組級別的管理,而不是塊級別的。
3.2.客戶端擴(kuò)展
? ??客戶端讀寫路徑被增強(qiáng),可以并行處理一個塊組的多個內(nèi)部塊;在輸出/寫入路徑,DFSStripedOutputStream 用于管理一組數(shù)據(jù)流,每個數(shù)據(jù)流對應(yīng)一個DataNode,該DataNode在當(dāng)前塊組中存儲一個內(nèi)部塊,這些數(shù)據(jù)流大多是異步工作;協(xié)調(diào)器負(fù)責(zé)操作整個塊組,包括結(jié)束當(dāng)前的塊組、分配新的塊組等等。在輸入 / 讀路徑,DFSStripedInputStream 將請求的邏輯字節(jié)范圍的數(shù)據(jù)轉(zhuǎn)換為存儲在DataNodes上的內(nèi)部塊的范圍,然后并行的發(fā)布讀請求,在出現(xiàn)故障時,它發(fā)出額外的讀請求用于解碼。
3.3.DataNode擴(kuò)展
? ??DataNode會運(yùn)行一個額外的ErasureCodingWorker (ECWorker)任務(wù)用于后臺恢復(fù)失敗的EC塊,當(dāng)NameNode檢測到一個失敗的EC塊,它會選擇一個DataNode去做恢復(fù)的工作,恢復(fù)任務(wù)通過心跳響應(yīng)傳遞至DataNode,這個過程類似于副本塊重新復(fù)制失敗的數(shù)據(jù)塊,重建失敗的塊有3個主要的任務(wù):
1)從源節(jié)點(diǎn)讀取數(shù)據(jù)
? ??使用專用的線程池并行的讀取輸入數(shù)據(jù),基于EC策略,它將所有的讀請求調(diào)度到所有的源節(jié)點(diǎn),并且只讀取最小數(shù)據(jù)量的輸入塊數(shù)用于重構(gòu)。
2)解碼數(shù)據(jù)并生成輸出數(shù)據(jù)
? ??從輸入數(shù)據(jù)中解碼出新的數(shù)據(jù)塊和奇偶校驗(yàn)塊,所有丟失的數(shù)據(jù)塊和校驗(yàn)塊一起解碼。
3)傳輸生成的數(shù)據(jù)塊到目標(biāo)節(jié)點(diǎn)
? ??解碼完成后,恢復(fù)的數(shù)據(jù)塊被傳輸?shù)侥繕?biāo)DataNode節(jié)點(diǎn)。
3.4.糾刪碼策略
? ??為了使糾刪碼策略適合異構(gòu)的工作方式,我們允許HDFS集群上的文件和目錄具有不同的副本和糾刪碼策略,糾刪碼策略封裝了如何編碼/解碼文件,每一個策略由以下信息部分定義:
3.4.1.EC約束
? ??這個包括在EC組(比如:6+3)中數(shù)據(jù)塊和校驗(yàn)塊的數(shù)量,以及編解碼器算法(比如:Reed-Solomon, XOR)
3.4.2.條帶單元的大小
????這決定了條帶讀寫的粒度,包括緩沖區(qū)大小和編碼工作。
????策略被命名為數(shù)據(jù)塊數(shù)量-校驗(yàn)塊數(shù)量-塊單元的大小,當(dāng)前支持6種內(nèi)置策略:RS-3-2-1024k,?RS-6-3-1024k,?RS-10-4-1024k,?RS-LEGACY-6-3-1024k,?XOR-2-1-1024k?和REPLICATION。
????REPLICATION是一種特殊的策略,它只能被設(shè)置在目錄上,強(qiáng)制目錄采用3副本策略,而不是繼承它的祖先的糾刪碼策略,該策略使3副本目錄與糾刪碼目錄交叉成為可能。
????REPLICATION?策略是一直啟用的,而其它的內(nèi)置策略在默認(rèn)的情況下是禁用的。
????類似于HDFS存儲策略,糾刪碼策略是設(shè)置在目錄上的,當(dāng)一個文件被創(chuàng)建,它繼承離它最近的祖先目錄的EC策略。
????目錄級別的EC策略只影響在該目錄下創(chuàng)建的新文件,一旦一個文件已經(jīng)被創(chuàng)建,它的糾刪碼策略可以被查詢,但是不能改變,如果一個糾刪碼文件被重命名到一個不同的EC策略的目錄中,該文件會保留它之前存在的EC策略,轉(zhuǎn)換一個文件到不同的EC策略需要重寫它的數(shù)據(jù),重寫數(shù)據(jù)是通過拷貝文件(比如:通過distcp)而不是重命名文件。
????我們允許用戶通過XML文件的方式去定義它們自己的EC策略,該XML文件必須要有下面的3部分:
????????1)layoutversion:?表示EC策略文件格式的版本。
????????2)schemas:這個包括所有用戶定義的EC約束
????????3)policies:?這個包括所有用戶定義的EC策略,每個策略由schema id和條帶單元的大小(cellsize)構(gòu)成,
????在hadoop conf目錄中有一個名稱叫 user_ec_policies.xml.template的樣本EC策略的XML文件。
<?xml version="1.0"?>
<!--
這是用戶定義EC策略配置的模板,所有的策略和約束都在'configuration'標(biāo)簽之內(nèi),'configuration'標(biāo)簽是該XML文檔的頂級元素,?'layoutversion'標(biāo)簽中包含該EC策略XML文件格式的版本,?'schemas'標(biāo)簽中包含用戶定義的EC約束,'policies' 標(biāo)簽中包含所有用戶定義的EC策略,每一個策略由schema id 和cellsize組成。
-->
<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>
3.5.IntelISA-L
? ??因特爾ISA-L代表因特爾智能存儲加速庫,ISA-L是為存儲應(yīng)用程序優(yōu)化的底層函數(shù)開源的集合,它包括在AVX 和AVX2指令集上快速的塊?Reed-Solomon類型的糾刪碼優(yōu)化,HDFS糾刪碼可以利用ISA-L去加速編解碼計(jì)算,ISA-L支持大多數(shù)開源的操作系統(tǒng),包括linux和windows,ISA-L默認(rèn)是不啟動的,有關(guān)如何啟動ISA-L,請看下面的說明。
4.部署
4.1.集群和硬件配置
????糾刪碼在集群的CPU和網(wǎng)絡(luò)方面提出了額外的要求。
????編碼和解碼工作會消耗HDFS客戶端和DataNodes上額外的CPU。
????糾刪碼文件也分布在機(jī)架之間,用于機(jī)架容錯,這意味著當(dāng)讀取和寫入條帶文件,大多數(shù)操作是在機(jī)架外的,因此,網(wǎng)絡(luò)對分帶寬非常重要的。
????對于機(jī)架容錯來說,至少擁有與配置的EC條帶寬度相同的機(jī)架數(shù)量也是很重要的,對于EC策略RS (6,3),這意味著至少要有9個機(jī)架,理想的情況下要有10或者11個機(jī)架用于處理計(jì)劃內(nèi)和計(jì)劃外的停機(jī)。對于機(jī)架數(shù)量少于條帶寬度的集群,HDFS不能維護(hù)機(jī)架容錯,但是仍然會分散條帶文件到多個節(jié)點(diǎn)為了節(jié)點(diǎn)級別的容錯。
4.2.配置的關(guān)鍵字
????默認(rèn)情況下,所有內(nèi)置的糾刪碼策略是被禁用的,但是定義在參數(shù)dfs.namenode.ec.system.default.policy中的除外,該策略在默認(rèn)情況下是啟用的。集群管理員可以根據(jù)集群的大小和希望的容錯屬性使用命令hdfs ec [-enablePolicy -policy <policyName>]啟用一組策略;例如,對于一個擁有9個機(jī)架的集群,類似RS-10-4-1024k?這樣的策略不能達(dá)到機(jī)架級別的容錯,而策略RS-6-3-1024k?或者RS-3-2-1024k更適合。如果管理員只關(guān)心節(jié)點(diǎn)級別的容錯,在至少有14個DataNodes的集群中策略RS-10-4-1024k也是適合的。
????系統(tǒng)默認(rèn)的EC策略可以通過參數(shù)‘dfs.namenode.ec.system.default.policy’ 來配置,在這種配置下,當(dāng)命令?‘-setPolicy’沒有指定策略名稱的參數(shù)時,默認(rèn)的策略將會被使用。
????默認(rèn)情況下,參數(shù)?‘dfs.namenode.ec.system.default.policy’ 的值為“RS-6-3-1024k”,使用Reed-Solomon和XOR實(shí)現(xiàn)的編解碼器可以使用客戶端和DataNode節(jié)點(diǎn)指定如下的關(guān)鍵字配置:io.erasurecode.codec.rs.rawcoders用來指定默認(rèn)的RS編解碼器,io.erasurecode.codec.rs-legacy.rawcoders用于指定legacy RS編解碼器,io.erasurecode.codec.xor.rawcoders用于指定XOR編解碼器;用戶也可以使用類似關(guān)鍵字io.erasurecode.codec.self-defined-codec.rawcoders來配置自定義的編解碼器。這些關(guān)鍵字的值是帶有回退機(jī)制的編碼器名稱的列表。這些編解碼器工廠以指定的配置的值有序的被加載,直到一個編解碼器被成功的加載,默認(rèn)的RS和XOR編解碼器配置更喜歡本地實(shí)現(xiàn),而不是純java實(shí)現(xiàn);RS-LEGACY沒有本地編解碼器實(shí)現(xiàn),因此默認(rèn)的只能是純java的實(shí)現(xiàn);所有這些編解碼器都有純java的實(shí)現(xiàn);對于默認(rèn)的RS編解碼器,它也有一個本地實(shí)現(xiàn),利用英特爾?ISA-L庫提高編解碼器性能;對于XOR編解碼器,也支持利用英特爾?ISA-L庫提升編解碼的性能的本地實(shí)現(xiàn);請參閱“Enable Intel ISA-L”獲取更詳細(xì)的信息。默認(rèn)的RSLegacy的實(shí)現(xiàn)是純java的,默認(rèn)的RS和XOR是使用了因特爾ISA-L庫本地實(shí)現(xiàn)的,在DataNodes上的糾刪碼后臺恢復(fù)工作也可以使用下面的參數(shù)被調(diào)優(yōu):
? ??1)dfs.datanode.ec.reconstruction.stripedread.timeout.millis--條帶讀取超時時間,默認(rèn)值 5000 ms
? ??2)dfs.datanode.ec.reconstruction.stripedread.buffer.size--讀取服務(wù)的緩存大小,默認(rèn)值 64K
? ??3)dfs.datanode.ec.reconstruction.threads-- DataNode用于后臺重構(gòu)工作的線程數(shù)量,默認(rèn)值 8 個線程
? ??4)dfs.datanode.ec.reconstruction.xmits.weight--與副本塊恢復(fù)相比,EC后臺恢復(fù)任務(wù)使用的xmits 的相對權(quán)重,默認(rèn)值0.5,設(shè)置它的值為0去禁用計(jì)算EC恢復(fù)任務(wù)的權(quán)重,也就是說,EC任務(wù)總是1 xmits。通過計(jì)算出讀數(shù)據(jù)流的數(shù)量和寫數(shù)據(jù)流的數(shù)量的最大值來計(jì)算出糾刪碼恢復(fù)任務(wù)的xmits。例如,如果一個EC恢復(fù)任務(wù)需要從6個節(jié)點(diǎn)讀取數(shù)據(jù),往2個節(jié)點(diǎn)寫入數(shù)據(jù),它擁有的 xmits 是max(6, 2) * 0.5 = 3,復(fù)制文件的恢復(fù)任務(wù)總是計(jì)算為1xmit,NameNode利用dfs.namenode.replication.max-streams減去DataNode上總的xmitsInProgress(合并來自副本文件和EC文件的xmits)?,以便調(diào)度恢復(fù)任務(wù)到這個DataNode。
4.3.啟用英特爾ISA-L
????HDFS利用因特爾ISA-L庫去提高默認(rèn)的RS本地實(shí)現(xiàn)的編解碼器的編解碼計(jì)算速度,開啟并使用英特爾ISA-L庫,需要3步:
????????1)構(gòu)建ISA-L庫,請參閱官方的網(wǎng)站?“https://github.com/01org/isa-l/” 獲取詳情信息。
? ? ? ? 2)構(gòu)建帶有ISA-L支持的Hadoop,請參閱源碼中BUILDING.txt文件中的?“Build instructions for Hadoop”中的“Intel ISA-L build options”部分。
? ? ? ? 3)使用-Dbundle.isal拷貝?isal.lib?目錄中的內(nèi)容到最終的tar文件中。
????使用該tar文件部署Hadoop,確保ISA-L是在HDFS客戶端和DataNodes端是可用的。為了驗(yàn)證ISA-L能夠被Hadoop正確的檢測到,運(yùn)行命令 ?hadoop checknative來驗(yàn)證。
4.4.管理員命令
????HDFS提供了EC的子命令用于執(zhí)行糾刪碼相關(guān)的管理命令。
????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>] [-help [cmd ...]]
????下面是關(guān)于每個命令的詳情:
4.4.1. -setPolicy
????[-setPolicy -path <path> [-policy <policyName>] [-replicate]]
????在指定的目錄的路徑上設(shè)置糾刪碼策略。
????path:HDFS中的目錄,這是一個強(qiáng)制的參數(shù),設(shè)置一個策略只影響新創(chuàng)建的文件,不影響已經(jīng)存在的文件。
????policyName:在這個目錄下的文件上使用的糾刪碼策略,如果配置了參數(shù)‘dfs.namenode.ec.system.default.policy’,這個參數(shù)可以被省略,這時路徑的EC策略將會被設(shè)置成配置文件中的默認(rèn)值。
????-replicate:在目錄上應(yīng)用指定的REPLICATION策略,強(qiáng)制目錄采用3副本復(fù)制方案。
????-replicate?和-policy <policyName>是可選的參數(shù),它們不能同時被指定。
4.4.2. -getPolicy
????[-getPolicy -path <path>]
????獲取在指定路徑上目錄或者文件的糾刪碼策略的詳情。
4.4.3. -unsetPolicy
????[-unsetPolicy -path <path>]
????取消之前使用setPolicy?在目錄上設(shè)置的糾刪碼策略。如果目錄是從祖先中繼承的糾刪碼策略,unsetPolicy?是一個空操作,即在沒有明確設(shè)置策略的目錄上取消策略將不會返回錯誤。
4.4.4. -listPolicies
????[-listPolicies?]
????列出所有在HDFS中注冊的糾刪碼策略,只有啟用的策略才能使用setPolicy?命令。
4.4.5. -addPolicies
????[-addPolicies -policyFile <file>]
????添加一個糾刪碼策略的列表,請參閱模板策略文件etc/hadoop/user_ec_policies.xml.template,最大的條帶單元大小被定義在屬性?‘dfs.namenode.ec.policies.max.cellsize’ 中,默認(rèn)值是4MB,當(dāng)前的HDFS中總共允許用戶添加64個策略,被添加的策略ID的范圍是64~127,如果已經(jīng)有64個策略被添加,再添加策略將會失敗。
4.4.6.?-listCodecs
????[-listCodecs]
????獲取系統(tǒng)中支持的糾刪碼編解碼器和coder列表。一個coder是一個編解碼器的實(shí)現(xiàn),一個編解碼器可以有不同的實(shí)現(xiàn),因此會有不同的coder,編解碼器的coders采用后備的順序被列出。
4.4.7. -removePolicy
????[-removePolicy -policy <policyName>]
????移除一個糾刪碼策略。
4.4.8. -enablePolicy
????[-enablePolicy -policy <policyName>]
????啟用一個糾刪碼策略
4.4.9. -disablePolicy
????[-disablePolicy -policy <policyName>]
????禁用一個糾刪碼策略。
5.局限性
????由于大量的技術(shù)挑戰(zhàn),在糾刪碼文件上不支持某些HDFS的寫操作,比如hflush,?hsync?和append操作。
????在糾刪碼文件上使用append()將會拋出IOException。
????在DFSStripedOutputStream?上執(zhí)行hflush()?和hsync()是空操作,因此,在糾刪碼文件上調(diào)用hflush()?或者h(yuǎn)sync()不能保證數(shù)據(jù)被持久化。
????客戶端可以使用StreamCapabilities?提供的API去查詢一個OutputStream?是否支持hflush()?和hsync(),如果客戶端渴望數(shù)據(jù)通過hflush()?和hsync()持久化,當(dāng)前的補(bǔ)救措施是在非糾刪碼目錄中創(chuàng)建3副本文件,或則使用FSDataOutputStreamBuilder#replicate()提供的API在糾刪碼目錄中創(chuàng)建3副本文件。