HDFS-RAID原理和實現


HDFS-RAID 是Facebook基於hadoop-20-append分支(第一代Hadoop)開發的raid方案,對HDFS的修改極少,主要包括為NameNode增加了根據block信息找到block所屬文件的接口。RAID的基本知識和目前社區的方案對比見,本文重點分析HDFS-RAID的原理和實現。

業界常用的編碼方式包括Reed-Solomon(RS),XOR,他們本質上都是對N個數據塊就行運算,產生K個校驗塊。這N+K個塊可以同時最多容忍K個塊的丟失,丟失的塊可以從其余的塊中的任意N個恢復出來。在HDFS-RAID里面,N叫做stripeLength,K叫做parityLength。在對數據塊和校驗塊的組織上,HDFS-RAID提供了兩種方式:

  1. 每個數據文件對應一個校驗文件,對數據文件的連續stripeLength個block進行編碼,產生parityLength個parity block,多個parity block組成parity文件存儲在HDFS上。例子:stripeLength=3,parityLength=2,數據文件有6個block,那么對這個數據文件做raid會產生4個parity block,這四個parity block被連接起來組成parity文件。數據文件和parity文件的存放路徑存在一定的規則,根據配置決定.
  2. 數據block可以從不同的數據文件中抽取進行組合,這種方式下,就不存在數據文件和parity文件的一一對應關系,這樣的組合用StripeInfo表示,里面包括:數據塊列表,校驗塊列表,編碼方式。並且為了容錯,這個信息需要持久化,實現中,這個信息可以以多個文件的形式存在本地硬盤(LocalStripeStore)上,也可以存在RDBMS(DBStripeStore)中。值得注意的是,在對某個block進行恢復的時候,需要根據corrupt block信息從StripeStore中取出用於恢復的stripeLength個block,而讀取這些block的數據需要拿到block所在的文件名等信息才能讀取,而NameNode不提供block到file的接口,所以HDFS-RAID為了NameNode增加了這樣的接口。

HDFS-RAID主要由三個模塊組成,一個包裝了DistributedFileSystem的DistributedRaidFileSystem,一個是RaidNode進程,另外一個RaidShell命令行工具。

DistributedRaidFileSystem

DistributedRaidFileSystem基於DistributedFileSystem,是一種FilterFileSystem,在DistributedFileSystem讀數據拋出BlockMissingException或者ChecksumException一場時,會構造
DecoderInputStream,構造的過程中,會做block fix過程,找到stripeLength個數據塊,啟動幾個線程同時讀取這幾個數據塊,decode完成將修復的block數據放入buf中,上層即可以進行讀取。
應用使用DistributedRaidFileSystem需要在hdfs-site.xml中設置:

<property>
  <name>fs.hdfs.impl</name>
  <value>or  g.apache.hadoop.dfs.DistributedRaidFileSystem</value>
</property>

其他配置見wiki

RaidNode

編碼

RaidNode的TriggerMonitor線程根據配置的策略(PolicyInfo)不斷的選擇符合RAID條件的文件,然后做RAID。做RAID有兩種方式,一種是單機(LocalRaidNode),另外一種是分布式(DistRaidNode),利用MapReduce Job。HDFS-RAID中有一個encodingUnit的概念,它是做RAID的單位,默認是1。以分布式做RAID為例,假設stripeLength=3, parityLength=1,encodingUnit=2, TriggerMonitor選出了兩個文件a和b,文件a有6個block, b有12個block,可以得出,a有6/3=2個stripe,b有12/3=4個stripe, encodeingUnit=2代表2個stripe作為一個unit,unit用EncodingCandidate表示,這個例子會產生三個EncodingCandidate。每個EncodingCandidate作為mapper的key,相應的PolicyInfo作為value寫入Job的Input文件_distRaid.op.list(Job目錄下)中作為一行。輸入文件由DistRaidInputFormat來解析。Mapper類是DistRaidMapper,map函數就是對輸入的EncodingCandidate范圍內的stripe做raid。做raid,需要讀stripeLength個塊數據,生成parityLength個校驗塊,默認會有4個線程來做讀操作,每個線程就是打開數據block所在的文件,並且seek到block的開始offset,然后將數據讀入readbuf中,每個block對應一個readbuf,同時有parityLength個writebuf,用於存編碼完成的parity塊。最后將生成的parity塊連成一個parity file。為了更安全,HDFS-RAID有一個ChecksumStore的概念,開啟后,會將數據block和校驗block的crc都存入ChecksumStore中,后續如果發現有block損壞,進行修復完成后,從ChecksumStore中取出以前block的crc進行比對,如果相等,說明恢復無誤,然后選擇一個DataNode將恢復的block發送過去。

采用RAID方式后,為了提高可用性,盡量不在同一個機器上存儲屬於同一個stripe group的兩個block,PlacementMonitor線程用來做這個。

修復

BlockIntegrityMonitor用來定期檢測corrupt的file,並進行修復。同樣,修復block有分布式和本地修復兩種方式。同樣,以DistBlockIntegrityMonitor為例,獲取corrupt file通過DFSck向NameNode獲得,拿到corrupt文件名以及對應的corrupt的塊個數后,調用FileCheckRunnable來檢查文件是否已經corrupt,這里的corrupt是對DistributedRaidFileSystem而言的,只要corrupt block所在的stripe group(包括stripeLength個數據塊和parityLength個parity塊)中有至少stripeLength個數據塊是好的,那么這個corrupt block就可以恢復,說明這個文件對於DistributeRaidFileSystem來說就是好的,沒有corrupt,在這種情況下,會提交一個Job對這些corrupt block進行修復。Mapper是ReconstructionMapper,輸入文件的內容是corrupt file。Mapper的map函數拿到corrupt file name,然后進行reconstruct,這塊的流程原理和編碼差不多,不再贅述。恢復成功block后,選擇一個DataNode,給它發送WRITE_BLOCK指令,並把數據發送給它。

策略

主要提供兩個配置文件raid.xml和raid-default.xml

raid.xml:

<configuration> 
	<policy name = "RaidTest1"> 
		// prefix指定的路徑下的文件(遞歸)被掃描檢查是否滿足RAID條件
		<srcPath prefix="/user/foxmailed/raidtest"/>
		// 引用raid-default.xml中定義的id
		<codecId>xor</codecId>
		<property> 
			<name>targetReplication</name> 
			<value>1</value> 
			<description>after RAIDing, decrease the replication factor of a file to this value.</description> 
		</property> 
		<property> 
			<name>metaReplication</name> 
			<value>1</value> 
			<description> replication factor of parity file</description> 
		</property> 
		<property> 
			// 一個文件只有2秒沒有修改過才有可能被RAID
			<name>modTimePeriod</name> 
			<value>2000</value> 
			<description> time (milliseconds) after a file is modified to make it a candidate for RAIDing 
			</description> 
		</property> 
	</policy>
	// fileList指定的文件每一行的文件是RAID的候選,編碼方式引用名為RaidTest1的policy
	<policy name = "RaidTest2">
        <fileList>/user/foxmailed/fileList.txt</fileList>
        <parentPolicy>RaidTest1</parentPolicy>
    </policy>
    
</configuration>

raid-default.xml中主要配置RaidNode支持的編碼類型

<configuration>
<property>
<name>raid.codecs.json</name>
<value>
[{
"id" : "rs", //編碼id,在raid.xml中用到,用來飲用具體的編碼
"parity_dir" : "/raidrs",//校驗文件存放的位置
"stripe_length" : 10, 
"parity_length" : 4, //10個data block編碼生成4個parity block
"priority" : 200,
"erasure_code" : "org.apache.hadoop.raid.ReedSolomonCode", //具體編碼類
"description" : "ReedSolomonCode code",
"simulate_block_fix": true
},
{
"id" : "xor",
"parity_dir" : "/raid",
"stripe_length" : 10, 
"parity_length" : 1,
"priority" : 100,
"erasure_code" : "org.apache.hadoop.raid.XORCode",
"description" : "XORCode code",
"simulate_block_fix": true
},
{
"id" : "dir-rs",
"parity_dir" : "/dir-raidrs",
"stripe_length" : 10, 
"parity_length" : 4,
"priority" : 400,
"erasure_code" : "org.apache.hadoop.raid.ReedSolomonCode",
"description" : "Directory ReedSolomonCode code",
"simulate_block_fix": false,
"dir_raid" : true //目錄級別的RAID
}
]
</value>
<description>JSon string that contains all Raid codecs</description>
</property>
</configuration>

實際上,少於2個block的文件不會被RAID。

參考資料

HDFS-RAID Wiki

HDFS-RAID

Hadoop 2.5.0


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM