1)硬件錯誤是常態而不是異常。錯誤檢測並快速自動恢復是HDFS的最核心設計目標
2)流式數據訪問。運行在HDFS上的應用主要是以流式讀爲主,做批量處理;更注重數據訪問的高吞吐量。
3)超大規模數據集。HDFS的一般企業級的文件大小可能都在TB級別或者PB級別,支持大文件存儲,而且提供整體上高的數據傳輸帶寬,一個單一的HDFS實例應該能支撐數以千萬計的文件,並且能在一個集羣裏擴展到數百個節點。
4)簡單一致性模型。HDFS的應用程序一般對文件實行一次性讀寫、多次讀的訪問模式。
5)移動計算比移動數據更簡單。對於大文件來說,移動數據比移動計算的代價要高。操作海量數據時效果越加明顯,這樣可以提高系統的吞吐量和減少網絡的擁塞。
6)異構軟硬平臺間的可移植性。這種特性便於HDFS作爲大規模數據應用平臺的推廣。
HDFS是一個主從結構的體系,HDFS集羣有一個NameNode(Master)和很多個DataNode (Slaves)組成。NameNode管理文件系統的元數據,DataNode存儲實際的數據。客戶端聯繫NameNode以獲取文件的元數據,而真正的文件I/O操作是直接和DataNode進行交互的。
NameNode就是主控制服務器,負責維護文件系統的命令空間並協調客戶端對文件的訪問,記錄命名空間內的任何改動或命名空間本身的屬性改動。
HDFS典型的部署是在一個專門的機器上運行NameNode,集羣中的其他機器各運行一個DataNode;也可以在運行NameNode的機器上同時運行DataNode,或者一臺機器上運行多個DataNode。這種一個集羣只有一個NameNode的設計大大簡化了系統架構。
HDFS的主要設計目標之一就是在故障情況下也能保證數據存儲的可靠性。HDFS具備了較爲完善的冗餘備份和故障恢復機制[http://cn.hadoop.org/doc/hdfs_design.html],可以實現在集羣中可靠地存儲海量文件。
1.5.1冗餘備份
HDFS將每個文件存儲成一系列數據塊,默認塊大小爲64M(可配置)。爲了容錯,文件的所有數據塊都會有副本(副本數量即複製因子也可配置)。HDFS的文件都是一次性寫入的,並且嚴格限制爲任何時候都只有一個寫用戶。DataNode使用本地文件系統存儲HDFS的數據,但是它對HDFS的文件一無所知,只是用一個個文件存儲HDFS的每個數據塊。當DataNode啓動時,它會遍歷本地文件系統,產生一份HDFS數據塊和本地文件對應關係的列表,並把這個報告發給NameNode,這就是快報告(Blockreport)。快報告包括了DataNode上所有塊的列表。
1.5.2機架感知
HDFS集羣一般運行在多個機架上,不同機架上的通信需要通過交換機。通常情況下,副本的存放策略很關鍵,機架內節點之間的帶寬比跨機架節點之間的帶寬要大,他能映像HDFS的可靠性和性能。HDFS採用機架感知(Rack-aware)的策略來改進數據的可靠性、可用性和網絡帶寬的利用率。通過機架感知,NameNode可以確定每個DataNode所屬的機架ID。一般情況下,當複製因子是3的時候,HDFS的部署策略是將一個副本放在同一機架上的另一個節點,一個副本存放在本地機架上的節點,最後一個副本放在不同機架上的節點。機架的錯誤遠比節點的錯誤少,這個策略可以防止整個機架失效時數據丟失,不會映像倒數據的可靠性和可用性,又能保證性能。
1.5.3心跳檢測
NameNode週期性地從集羣中的每個DataNode接受心跳包和塊報告,收到心跳包說明該DataNode工作正常。NameNode會標記最近沒有心跳的DataNode爲死機,不會發給他們任何新的I/O請求。任何存儲在死機的DataNode的數據將不再有效,DataNode的死機會造成一些數據塊的副本數下降並低於指定值。NameNode會不斷檢測這些需要複製的數據塊,並在需要的時候重新複製。重新複製的引發可能有多種原因,比如DataNode不可用、數據副本的損壞、DataNode上的磁盤錯誤或複製因子增大等。
系統啓動時,NameNode會進入一個安全模式。此時不會出現數據塊的寫操作。NameNode會收到各個DataNode擁有的數據塊列表對的數據塊報告,因此NameNode獲得所有的數據塊信息。數據塊達到最小副本數時,該數據塊就被認爲是安全的。在一定比例(可配置)的數據塊被NameNode檢測確認是安全之後,再等待若干時間,NameNode自動推出安全模式狀態。當檢測到副本數不足的數據塊時,該塊會被複制到其他數據節點,以達到最小副本數。
多種原因會造成從DataNode獲取的數據塊有可能是損壞的。HDFS客戶端軟件實現了對HDFS文件內容的校驗和(Checksum)檢查,在HDFS文件創建時,計算每個數據塊的校驗和,並將校驗和作爲一個單獨的隱藏文件保存在命名空間下。當客戶端獲取文件後,它會檢查從DataNode獲得的數據塊對應的校驗和是否和隱藏文件中的相同,如果不同,客戶端就會認爲數據塊有損壞,將從其他DataNode獲取該數據塊的副本。
文件被用戶或應用程序刪除時,並不是立即就從HDFS中移走,而是先把它移動到/trash目錄裏。只要還在這個目錄裏,文件就可以被迅速恢復。文件在這個目錄裏的時間是可以配置的,超過了這個時間,系統就會把它從命名空間中刪除。文件的刪除操作會引起相應數據塊的釋放,但是從用戶執行刪除操作到從系統中看到剩餘空間的增加可能會有一個時間延遲。只要文件還在/trash目錄裏,用戶可以取消刪除操作。當用戶想取消時,可以瀏覽這個目錄並取回文件,這個目錄只保存被刪除文件的最後一個副本。這個目錄還有一個特性,就是HDFS會使用特殊策略自動刪除文件。當前默認的策略是:文件超過6個小時後自動刪除,在未來版本里,這個策略可以通過定義良好的接口來配置。
1.5.7映像文件和事務日誌多副本
映像文件和事務日誌是HDFS的核心數據結構。如果這些文件損壞,將會導致HDFS不可用。NameNode可以配置爲支持維護映像文件和事務日誌的多個副本,任何對映像文件或事務日誌的修改,都將同步到他們的副本上。這樣會降低NameNode處理命名空間事務的速度,然而這個代價是可以接受的,因爲HDFS是數據密集,而非元數據密集的。當NameNode重新啓動時,總是選擇最新的一致的映像文件和事務日誌。在HDFS集羣中NameNode是單點存在的,如果它出現故障,必須手動干預。目前,還不支持自動重啓或切換到另外的NameNode。
1.5.8快照
快照支持存儲在某個時間的數據複製,當HDFS數據損壞時,可以回滾到過去一個已知正確的時間點。HDFS目前還不支持快照功能。
HDFS被設計爲支持非常大的文件,他的應用都是處理大數據集的。高效的數據存儲也是Hadoop的優點之一。
1.4.1副本選擇
HDFS會盡量使用離程序最近的副本來滿足用戶請求,這樣可以減少總帶寬消耗和讀延時。如果在讀取程序的同一個機架有一個副本,那麼就使用這個副本;如果HDFS集羣跨了多個數據中心,那麼讀取程序將有限考慮本地數據中心的副本。
1.4.2負載均衡
HDFS的架構支持數據均衡策略。如果某個DataNode的剩餘磁盤空間下降到一定程度,按照均衡策略,系統會自動把數據從這個DataNode移動到其他節點。當出現對某文件有很高的需求是,系統可能會啓動一個計劃創建該文件的副本,並重新平衡集羣中的其他數據。目前這些均衡策略還沒有實現。
1.4.3客戶端緩存
客戶端創建文件的請求不是立即到達NameNode,HDFS客戶端先把數據緩存到本地的一個臨時文件,程序的寫操作透明地重定向到這個臨時文件。當這個臨時文件累積的數據超過一個塊的大小時,客戶端纔會聯繫NameNode。NameNode在文件系統中插入文件名,給他分配一個數據塊,告訴客戶端DataNode的ID和目標數據塊ID,這樣客戶端就把數據從本地的緩存刷新到指定的數據塊中。當文件關閉後,臨時文件中剩餘的未刷新數據也會被傳輸到DataNode中,然後客戶端告訴NameNode文件已關閉,此時NameNode纔將文件創建操作寫入日誌進行存儲。如果NameNode在文件關閉之前死機,那麼文件將會丟失。如果不採用客戶端緩存,網絡速度和擁塞都會對輸出產生很大的影響。
1.4.4流水線複製
當客戶端要寫數據到HDFS的文件中時,就像前面介紹的那樣,數據一開始會寫入本地臨時文件。假設該文件的複製因子是3,當本地臨時文件累積到一個數據塊的大小時,客戶端會從NameNode獲取一個副本存放的DataNode列表,列表中的DataNode都將保存那個數據塊的一個副本。客戶端首先向第一個DataNode傳輸數據,第一個DataNode一小塊一小塊(4KB)地接受數據,寫入本地哭的同時,把接受到的數據傳輸給列表中的第二個DataNode;第二個DataNode以同樣的方式邊收邊傳,把數據傳輸給第三個DataNode;第三個DataNode把數據寫入本地庫。DataNode從前一個節點接受數據的同時,即時把數據傳給後面的節點,這就是流水線複製。dfs.replication=3,dfs.replication.min=1,只要寫入了一個成功了就認爲成功,其他的副本會在集羣中異步複製完成。
壓縮格式 | 工具 | 算法 | 文件擴展名 | 多文件 | 可分割性 | Java 實現 | 本地實現 |
DEFLATE | 無 | DEFLATE | .deflate | 不 | 不 | 是 | 是 |
gzip | gzip | DEFLATE | .gz | 不 | 不 | 是 | 是 |
bzip2 | bzip2 | bzip2 | .bz2 | 不 | 是 | 是 | 否 |
LZO | lzop | LZO | .lzo | 不 | 不 | 否 | 是 |
Java的序列化機制的缺點就是計算量開銷大,且序列化的結果體積大太,有時能達到對象大小的數倍乃至十倍。它的引用機制也會導致大文件不能分割的問題。這些缺點使得Java的序列化機制對Hadoop來說是不合適的。於是Hadoop設計了自己的序列化機制。