天天看點

HDFS的block Id與generation stamp

hdfs的資料是以block為機關存儲的,是以了解block的結構對了解hdfs的工作機制非常重要。

先來看一下Block類,它含有三個成員:blockId,numBytes和generationStamp。numBytes即block的大小,而另外兩個分别是什麼呢?blockId是block的辨別符,可以從block檔案名中看到,例如${hadoop.tmp.dir}/dfs/data/current/blk_826540629399449945,這一串數字就是blockId。同目錄下另一個meta檔案,如blk_826540629399449945_1017.meta,1017即是generationStamp。從Block類本身可以看到,generationStamp在compare、equals等操作上起到一個對blockId的輔助作用,由此猜測多個blocks可能擁有相同的blockId,彼此的generationStamp不同。

根據[1],早期block id是一個64位數随機數。當時實作比較簡單,并沒有判重,是以如果兩個block碰巧得到同樣的block id,系統會誤認為是多餘的備份block,而将其中一些删除。這樣這個block很有可能出錯,包含它的檔案則損壞。解決的辦法有兩個,一是記錄好所有使用過的block id,以實作判重功能;二是以一種不會重複的方式生成block id,比如順序生成。順序生成的缺點有3個,1是現有的系統遷移困難,所有的block都要重新命名;2是用完了64位數後仍然有麻煩;3是要記錄好最高的block id。[1]暫時實作了判重功能。

判重并不是最優的方法,因為它需要額外的工作,而且随着檔案系統變得龐大将變重。假設用一個Hash實作判重,一個1PB的檔案系統,假設1個block大小64MB,則包含有16M個block id,每個id為8個byte,則需要一個128MB的Hash表,這對于一個本身就很複雜的NameNode是個不小的壓力。[2]中提出了一種綜合的方法,給一個檔案的所有block指定一個相同的range id(5個byte)作為它們block id的高位,然後按順序每個block生成剩餘的3個byte。較之前的單純判重,好處在于減小了判重的數量;同時又友善管理同一個檔案的block,因為它們的block id是連續的。[2]也指出這種方法的問題,當一個檔案被删除時,此range id要從系統中抹去,如果此時某個包含此檔案某block的資料結點掉線了,在它重新上線之後,它又帶回這個已經無效的range id。是以需要timestamps,即creation time of the file,當兩個檔案碰巧有相同的range id時,根據timestamps來判定誰是最新的檔案,舊的檔案将被删除。[2]中能看到Doug Cutting和Sameer Paranjpye的一些其它討論,比如range-id也采用順序生成(又回到随機VS順序的問題上)。

[1]和[2]都是在07年的0.1版本上的討論,現在0.20.2的版本是什麼情況呢?我們先來看一下代碼吧!FSNamesystem的allocateBlock方法:

  private Block allocateBlock(String src, INode[] inodes) throws IOException {

    Block b = new Block(FSNamesystem.randBlockId.nextLong(), 0, 0); 

    while(isValidBlock(b)) {

      b.setBlockId(FSNamesystem.randBlockId.nextLong());

    }

    b.setGenerationStamp(getGenerationStamp());

    b = dir.addBlock(src, inodes, b);

    NameNode.stateChangeLog.info("BLOCK* NameSystem.allocateBlock: "

                                 +src+ ". "+b);

    return b;

  }

這裡block id還是用一個随機産生器生成的,并且用一個Map來判重,并沒有上面提到的range id的概念。同時,賦與block一個GenerationStamp,此stamp是檔案系統裡的全局變量,會在每次建立新檔案及其它一些block操作時順序增長。關于它的具體作用是不是[2]中所提到的,還需要進一步閱讀代碼。而關于block id的順序生成的問題上,今年在[3]中又有了新的討論,可能要等到0.23.0的版本才能看到結果吧。

參考:

[1] potential conflict in block id's, leading to data corruption

    https://issues.apache.org/jira/browse/HADOOP-146

[2] dfs should allocate a random blockid range to a file, then assign ids sequentially to blocks in the file

    https://issues.apache.org/jira/browse/HADOOP-158

[3] Sequential generation of block ids

    https://issues.apache.org/jira/browse/HDFS-898

  原文連結: http://hi.baidu.com/jay23jack/blog/item/388d770bb4db20b72fddd40f.html

轉載于:https://www.cnblogs.com/aaronwxb/archive/2012/09/16/2687587.html

繼續閱讀