HDFS-RAID原理和實現

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

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

  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命令行工具。git

DistributedRaidFileSystem

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

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

其餘配置見wikiapache

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發送過去。json

採用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指令,並把數據發送給它。app

策略

主要提供兩個配置文件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

相關文章
相關標籤/搜索