首先GFS的設計目標包括易擴展,幾乎線性擴展成大規模的集羣運;行在通用和廉價的硬體上提供可靠的容錯機制並且滿足高吞吐的性能要求。
在論文的開頭就對GFS系統的運行作了假設: 1. 硬體失效是經常發生的,因為伺服器都是通用的相對於廉價的硬體(不過現在Google都已經全部用定製化的企業級硬體了); 2. 數GB到數TB的大文件,Google的大數據場景,數據都非常的大,單個數據文件都非常的大,另外有一點是大文件可以減少文件的數量,降低元數據的數量; 3. 寫一次讀多次,而且幾乎是追加寫,很少覆蓋寫,讀也大塊順序讀較多; 4. 不兼容通用的POSIX文件介面,採用應用與系統一體的設計,這樣他的IO路徑不需要經過內核態的inode等,縮短了IO的路徑。5. 高帶寬比低時延更重要,這是由Google本身的業務場景所決定的;
GFS主要是包括3種基本角色:client、master、chunk server,client實現各種API以庫的形式提供給業務應用使用;master是全局元數據的管理者,包含name space管理,chunk數據分佈管理等等,它是GFS集羣的核心; chunk server即是實現數據存儲,把文件切分成chunk分成多副本存儲到多個chunk server上實現數據的可靠性;
client提供的介面不是POSIX介面,主要提供以下create/delete/open/close/read/write/snapshot/record append 等功能介面。client作為api庫鏈接到具體的應用 它不需要經過內核態的inode層。直接通過網路訪問chunk server 或者master更加的高效;它從master獲取metadata並緩存在本地內存中,然後直接與chunk server交互,讀寫IO不必每次都經過master,使master不會成功瓶頸;
client側不提供數據cache機制,主要出於以下原因考慮: 1. 應用場景為大文件的順序讀,需要大內存,而且收益很低; 2. cilent的設計更簡單,client有cache的話需要複雜的機制才能保證多client之間的數據一致性,比如分散式鎖等; 3. chunkserver用的是本地文件系統具有buffer cache,它會緩存經常訪問的數據,這樣chunk server側在一定程度上緩存了熱點數據;
查詢是批量查的,比如一次io可能跨多個chunk,那麼多個chunk server的信息包括副本的一次返回,這要可以減少網路交互的次數。
?
為了充分利用chunk server的帶寬,各個副本的chunk server採用串列寫的方式。每一次轉發都是轉發給自己最近的chunk副本,採用流水線操作降低時延,因為網路都是全雙工的,所以數據在接收的同時是可以發送的;
傳統寫是帶有數據與offset的,但是追加寫是僅帶有數據,多個client並發寫的時候,系統至少一次原子將數據追加到文件的後面(類似文件以O_APPEND的方式打開),寫成功之後把file的offset返回給client,這樣上層可以增加一層邏輯構建不同方式的存儲系統,追加寫是現代分散式系統的更願意選擇的方式,因為它的順序寫特性無論對硬碟還是對SSD都是比較友好;另外不是追加寫的話,要支持多client共享寫需要複雜的額外方式來保證,比如分散式鎖等,追加寫用很少的代價就可以保證數據是defined的。
單一master使設計更加的簡單,單一master並不表示數據只有一份,而是表示單個master擁有全部的元數據,它擁有全局的chunk信息可以更精準的控制數據的分佈,另一方面,讀寫io除首io外幾乎不需要master參與,所以master也不會成為性能瓶頸。
每個chunk所需的元數據大小小於64位元組,name space 的路徑名前綴用採用壓縮的方式存儲進一步減小元數據的大小,使得所有元數據全部保全在master的內存中,filename到元數據是一個lookup table mapping每個目錄個文件的元數據都分別有讀寫鎖進行保護。主要有4種元數據信息:a. 許可權控制信息;b. file namespace信息;c. file到chunk之間的映射;d. chunk的位置信息。namespace和file到chunk之間的映射以操作日誌的方式記錄在硬碟上;當前的chunk位置信息不持久化在master的上master啟動或者chunk server啟動的時候通報chunk 位置信息。後續master與chunk server之間通過心跳報告chunk狀態,主要原因是伺服器損壞在大規模集羣中是經常發生的事,所以週期去查詢的辦法比固化信息更加簡單來保證集羣的一致性。
租約用於對chunk的修改,租約有超時時間,在到期前可以續約,可以減輕master的負載。通過chunk server與master之間的週期heartbeat來續約。
文件刪除之後並不是馬上刪除chunk的,而是有後臺垃慢慢刪除的,這樣的設計更加簡單和可靠,誤刪也有機會恢復。
元數是非常重要的,它是GFS文件系統的核心,需要記錄多份,根據時間線記錄元數據操作的所有記錄,只有操做log持久化成功(所有副本flush成功)以後才修改內存的內容讓client可見,避免持久化異常而導致的不一致。用checkpoint機制使恢復回放的時間盡量短。它是一個簡潔的B tree,可以直接映射到內存,不需要額外的解析。建立checkpoint是需要時間的,它的操作會影響新的修改,解決辦法是另起一個線程建立checkpoint,新的修改另起一個log文件。 建立好checkpoint之後並不是立刻刪掉log文件,它會保存checkpoint附近的log文件,保證操作log的可靠性,比如checkpoint建立不完整。
chunk server 上保存具體的數據,每個chunk的大小為64M,每個chunk具有全局的64位的handle id; 每個chunk file又多個備份分佈在不同的chunk server上,一般為3備份,備份數可以根據命名空間區域分別指定。
因為只在master上創建file,所以用namespace lock來保證即可,每個目錄和文件都有讀寫鎖保護,精細化的鎖使master不會成為瓶頸。另外,還有操作日誌來確定它的操作順序。
文件的修改狀態取決於修改的方式,比如單client還是多client並發寫,是追加寫還是覆蓋寫,是寫成功還是寫失敗。
附:
快照採用COW(copy on write)的方式,這種方式具有更快的速度,只有再寫file的時候再copy,不寫的話就是一個引用計數,這也更省空間。
作用是chunk server對於比較少讀的數據可以提前發現錯誤,避免靜默錯誤造成數據丟失。
主要用於問題定位,調試和性能分析;它主要是通過記錄伺服器各種事件。所有的RPC請求和回復消息,除了正在讀寫的IO。RPC日誌是非同步和順序記錄的,消耗很少的資源。