此文件定義了相容於 Hadoop 的檔案系統的必要行為,供 Hadoop 檔案系統的實作人員和維護人員,以及 Hadoop 檔案系統 API 的使用者參考
大多數 Hadoop 操作都會在 Hadoop 測試套件中針對 HDFS 進行測試,最初透過 MiniDFSCluster
進行,在供應商特定的「生產」測試釋出之前進行,並由其上方的 Hadoop 堆疊隱含進行。
HDFS 的動作是根據 POSIX 檔案系統行為建模,使用 Unix 檔案系統動作的動作和回傳碼作為參考。即便如此,HDFS 仍有與預期的 POSIX 檔案系統行為不同的部分。
隨附的 S3A 檔案系統用戶端透過檔案系統 API 使 Amazon 的 S3 物件儲存空間(「blobstore」)可以存取。Azure ABFS、WASB 和 ADL 物件儲存空間檔案系統會與 Microsoft 的 Azure 儲存空間通訊。所有這些都繫結到物件儲存空間,其行為不同,特別是在一致性保證和操作的原子性方面。
「本機」檔案系統提供對平台底層檔案系統的存取。其行為由作業系統定義,且可能與 HDFS 不同。本機檔案系統怪癖的範例包括大小寫敏感性、嘗試將檔案重新命名為另一個檔案上方的動作,以及是否可以 seek()
超過檔案的結尾。
也有由第三方實作的檔案系統,宣稱與 Apache Hadoop 相容。沒有正式的相容性套件,因此除了透過自己的相容性測試之外,沒有人可以宣稱相容性。
這些文件不會嘗試提供相容性的規範定義。通過相關的測試套件並不能保證應用程式的正確行為。
測試套件定義的是預期的動作集,未通過這些測試將會突顯潛在問題。
透過讓合約測試的每個面向都可設定,就能宣告檔案系統如何偏離標準合約的部分內容。這項資訊可以傳達給檔案系統的使用者。
本文檔遵循 RFC 2119 規則,關於 MUST、MUST NOT、MAY 和 SHALL 的使用。MUST NOT 視為規範性。
原始的 FileSystem
類別及其用法基於一組隱含假設。主要是 HDFS 是底層 FileSystem,且它提供 POSIX 檔案系統行為的子集(或至少是 Linux 檔案系統提供的 POSIX 檔案系統 API 和模型的實作)。
不論 API 為何,預期所有相容於 Hadoop 的檔案系統都呈現 Unix 中實作的檔案系統模型
它是一個包含檔案和目錄的階層式目錄結構。
檔案包含零或多個位元組的資料。
您無法將檔案或目錄放在檔案底下。
目錄包含零或多個檔案。
目錄項目本身沒有資料。
您可以將任意二進位資料寫入檔案。當檔案內容從叢集內部或外部的任何地方讀取時,會傳回資料。
您可以在單一檔案中儲存數十億個位元組的資料。
根目錄 "/"
始終存在,且無法重新命名。
根目錄 "/"
始終是目錄,且無法被檔案寫入作業覆寫。
任何遞迴刪除根目錄的嘗試都會刪除其內容(除非缺乏權限),但不會刪除根路徑本身。
您無法將目錄重新命名/移動到其自身底下。
您無法將目錄重新命名/移動到任何現有檔案之上,除了來源檔案本身。
目錄清單會傳回目錄中的所有資料檔案(即可能會有隱藏的檢查和檔案,但會列出所有資料檔案)。
目錄清單中檔案的屬性(例如擁有者、長度)與檔案的實際屬性相符,且與從開啟的檔案參考中檢視的內容一致。
安全性:如果呼叫者沒有執行作業的權限,則會失敗並引發錯誤。
路徑由以 "/"
分隔的路徑元素組成。
路徑元素是由 1 個或多個字元的 unicode 字串。
路徑元素不得包含字元 ":"
或 "/"
。
路徑元素不應包含 ASCII/UTF-8 值為 0-31 的字元。
路徑元素不得為 "."
或 ".."
另請注意,Azure blob 儲存文件指出路徑不應使用尾隨 "."
(因為其 .NET URI 類別會將其移除)。
路徑根據 unicode 碼點進行比較。
不得使用不區分大小寫和特定語言環境的比較。
除了安全性專門部分外,本文件假設用戶端擁有對檔案系統的完全存取權。因此,清單中的大多數項目不會加上「假設使用者有權限使用提供的參數和路徑執行操作」的限定條件。
未指定使用者缺乏安全性權限時的失敗模式。
本文件假設所有網路操作都會成功。所有陳述都可以假設為限定為「假設操作不會因網路可用性問題而失敗」
網路故障後檔案系統的最終狀態未定義。
網路故障後檔案系統的立即一致性狀態未定義。
如果可以向用戶端報告網路故障,則故障必須是 IOException
或其子類別的執行個體。
例外狀況詳細資料應包含適合有經驗的 Java 開發人員或運作團隊開始診斷的診斷。例如,ConnectionRefused 例外狀況的來源和目的地主機名稱和埠。
例外狀況詳細資料可以包含適合沒有經驗的開發人員開始診斷的診斷。例如,Hadoop 會嘗試在 TCP 連線要求被拒絕時包含對 ConnectionRefused 的參考。
以下是與 Hadoop 相容檔案系統的核心預期。有些檔案系統不符合這些預期;因此,有些程式可能無法如預期般運作。
有些作業必須是原子性的。這是因為它們通常用於在叢集中的程序之間實作鎖定/獨佔存取。
overwrite
參數為 false,則檢查和建立必須是原子性的。mkdir()
建立單一目錄。大多數其他作業都沒有原子性需求或保證。
Hadoop FileSystem 的一致性模型是 one-copy-update-semantics;傳統的本機 POSIX 檔案系統也是如此。請注意,即使 NFS 也放寬了一些關於變更傳播速度的限制。
建立。一旦寫入新建立檔案的輸出串流上的 close()
作業完成,叢集內部查詢檔案的元資料和內容的作業必須立即看到檔案及其資料。
更新。一旦寫入新建立檔案的輸出串流上的 close()
作業完成,叢集內部查詢檔案的元資料和內容的作業必須立即看到新的資料。
刪除。一旦對非 “/” 路徑的 delete()
作業成功完成,它就必須不可見或不可存取。特別是,listStatus()
、open()
、rename()
和 append()
作業都必須失敗。
刪除然後建立。當刪除一個檔案然後建立一個同名的新檔案時,新檔案必須立即可見,且其內容可透過 FileSystem API 存取。
重新命名。在 rename()
完成後,針對新路徑的作業必須成功;嘗試針對舊路徑存取資料必須失敗。
叢集內部的一致性語意必須與叢集外部的一致。查詢未積極處理的檔案的所有用戶端都必須看到相同的元資料和資料,而與其位置無關。
無法保證對資料的隔離存取:如果一個用戶端正在與遠端檔案互動,而另一個用戶端變更該檔案,則變更可能可見或不可見。
所有作業都必須最終完成,無論成功或失敗。
完成操作所需時間未定義,可能會取決於實作和系統狀態。
操作可能會擲出 RuntimeException
或其子類別。
操作應將所有網路、遠端和高層級問題作為 IOException
或其子類別引發,且不應為此類問題引發 RuntimeException
。
操作應透過引發例外,而非操作的特定回傳碼,來報告失敗。
在文字中,當命名例外類別時,例如 IOException
,引發的例外可能是命名例外或其子類別的執行個體。它不能是超類別。
如果操作未在類別中實作,實作必須擲出 UnsupportedOperationException
。
實作可能會重試失敗的操作,直到成功為止。如果他們這麼做,應以這樣的方式進行,使得任何操作順序之間的 發生在之前 關係符合所述的一致性和原子性需求。請參閱 HDFS-4849 以取得此範例:HDFS 沒有實作任何其他呼叫者可以觀察到的重試功能。
以下是從未明確定義的 FileSystem 容量限制。
目錄中的最大檔案數目。
目錄中的最大目錄數目
檔案系統中的最大總項目數目(檔案和目錄)。
目錄下檔案名的最大長度(HDFS:8000)。
MAX_PATH
- 參照檔案的整個目錄樹的總長度。Blobstore 傾向於在 ~1024 個字元處停止。
路徑的最大深度(HDFS:1000 個目錄)。
單一檔案的最大大小。
操作的逾時完全未定義,包括
封鎖 FS 操作的最大完成時間。MAPREDUCE-972 文件說明 distcp
如何在 s3 重新命名變慢時中斷。
關閉前閒置讀取串流的逾時。
關閉前閒置寫入串流的逾時。
封鎖操作逾時在 HDFS 中實際上是變數,因為網站和客戶端可能會調整重試參數,以將檔案系統故障和故障轉換為操作暫停。相反地,有一個普遍的假設,即 FS 操作「快速,但不如本機 FS 操作快速」,而且資料讀取和寫入的延遲會隨著資料量而擴充。客戶端應用程式的此假設揭示了一個更基本的假設:檔案系統在網路延遲和頻寬方面「接近」。
對於某些操作的開銷也有一些隱含的假設。
seek()
操作快速,而且幾乎沒有或沒有網路延遲。[這不適用於 blobstore]
對於項目較少的目錄,目錄清單操作快速。
目錄清單作業對於條目較少的目錄執行起來很快,但可能會產生成本為 O(entries)
。Hadoop 2 加入反覆清單,以因應列出數百萬個條目的目錄的挑戰,而不會以一致性為代價進行緩衝。
OutputStream
的 close()
很快,無論檔案作業是否成功。
刪除目錄的時間與子條目的數量無關
此規格在某些地方會提到「物件儲存空間」,通常會使用「Blobstore」一詞。Hadoop 確實為其中一些提供檔案系統用戶端類別,即使它們違反許多需求。
請參閱特定儲存空間的說明文件,以確定其與特定應用程式和服務的相容性。
什麼是物件儲存空間?
物件儲存空間是一種資料儲存服務,通常透過 HTTP/HTTPS 存取。PUT
要求會上傳物件/「Blob」;GET
要求會擷取它;範圍 GET
作業允許擷取 Blob 的部分。若要刪除物件,會呼叫 HTTP DELETE
作業。
物件會依名稱儲存:一個字串,其中可能包含「/」符號。沒有目錄的概念;可以在物件中指定任意名稱,但須符合服務提供者所施加的命名原則限制。
物件儲存空間不變地提供一個作業,以擷取具有特定前綴的物件;在服務的根目錄上執行 GET
作業,並使用適當的查詢參數。
物件儲存空間通常會優先考慮可用性,沒有與 HDFS NameNode(s) 相等的單一故障點。它們也致力於簡單的非 POSIX API:HTTP 動詞是允許的作業。
Hadoop 檔案系統用戶端會嘗試讓物件儲存空間假裝自己是檔案系統,一個具有與 HDFS 相同功能和作業的檔案系統。這最終只是一個假象:它們具有不同的特性,而且有時會發生幻覺失效的情況。
一致性。物件可能為最終一致性:物件的變更(建立、刪除和更新)可能需要一些時間才能讓所有呼叫者看見。的確,無法保證變更會立即對剛做出變更的客戶端可見。例如,物件 test/data1.csv
可能會被新的資料集覆寫,但當在更新後不久進行 GET test/data1.csv
呼叫時,會傳回原始資料。Hadoop 假設檔案系統是一致的;建立、更新和刪除會立即可見,且列出目錄的結果會與目錄內的檔案即時更新。
原子性。Hadoop 假設目錄 rename()
作業是原子的,delete()
作業也是。物件儲存體 FileSystem 客戶端會將這些作業實作為對名稱與目錄字首相符的個別物件的作業。因此,變更會一次處理一個檔案,且不是原子的。如果作業在處理過程中失敗,物件儲存體的狀態會反映部分完成的作業。另請注意,客戶端程式碼假設這些作業為 O(1)
,在物件儲存體中,它們更有可能是 O(子項目)
。
耐用性。Hadoop 假設 OutputStream
實作會在 flush()
作業中將資料寫入其(持續性)儲存體。物件儲存體實作會將所有寫入資料儲存在本機檔案中,然後在最後的 close()
作業中才將該檔案 PUT
到物件儲存體中。因此,絕不會有來自不完整或失敗作業的部分資料。此外,由於寫入程序僅在 close()
作業中開始,因此該作業可能需要與要上傳的資料量成正比的時間,且與網路頻寬成反比。它也可能失敗,而失敗比忽略更好。
授權。Hadoop 使用 FileStatus
類別來表示檔案和目錄的核心元資料,包括擁有者、群組和權限。物件儲存體可能沒有可行的途徑來儲存這些元資料,因此可能需要使用暫存值填入 FileStatus
。即使物件儲存體儲存這些元資料,物件儲存體仍然可能無法像傳統檔案系統一樣強制執行檔案授權。如果物件儲存體無法儲存這些元資料,建議的慣例如下:
具有這些特性的物件儲存體無法用於直接取代 HDFS。就本規格而言,它們對指定作業的實作與所需實作不符。Hadoop 開發社群將其視為受支援,但程度不如 HDFS。
FileStatus
條目有修改時間和存取時間。
HDFS 檔案系統在寫入時不會更新修改時間。
具體來說
FileSystem.create()
建立:列出一個零位元組檔案;修改時間設定為 NameNode 上看到的目前時間。create()
呼叫傳回的輸出串流寫入檔案:修改時間不會變更。OutputStream.close()
時,會寫入所有剩餘資料,關閉檔案,並以檔案的最終大小更新 NameNode。修改時間設定為檔案關閉的時間。append()
作業開啟檔案以附加資料,不會變更檔案的修改時間,直到對輸出串流進行 close()
呼叫。FileSystem.setTimes()
可用於明確設定檔案的時間。FileSystem.concat()
、createSnapshot()
、createSymlink()
和 truncate()
都會更新修改時間。dfs.namenode.access.time.precision
;預設精確度為 1 小時。如果將精確度設定為零,則不會記錄存取時間。FileStatus
欄位的數值為 0。其他檔案系統可能會有不同的行為。特別是
物件儲存體對時間的觀點更模糊,可以總結為「它會變動」。
FileStatus.getAccessTime() == 0
。create()
呼叫的時間,或是實際發起 PUT 要求的時間。這可能是 FileSystem.create()
呼叫、最後的 OutputStream.close()
作業,或介於兩者之間的某個時間。close()
呼叫中更新。FileSystem.setTimes()
作業可能會被忽略。FileSystem.chmod()
可能會更新修改時間(範例:Azure wasb://
)。FileSystem.append()
,變更和修改時間可能會在輸出串流關閉後才變得可見。rename()
作業通常實作為 COPY + DELETE,因此重新命名物件的時間戳記可能會變成物件重新命名開始的時間,而不是來源物件的時間戳記。最後,請注意 Apache Hadoop 專案無法保證遠端物件儲存體的時間戳記行為會隨著時間保持一致:它們是第三方服務,通常透過第三方函式庫存取。
這裡最好的策略是「針對您打算使用的確切端點進行實驗」。此外,如果您打算使用任何快取/一致性層,請在啟用該功能的情況下進行測試。在更新 Hadoop 版本和端點物件儲存之後,請重新測試。