本文是讀GFS論文的總結,收錄在個人github中papers項目,papers項目旨在學習和總結分佈式系統相關的論文。git
全文主要分爲如下幾方面:github
google對現有系統的運行狀態以及應用系統進行總結,抽象出對文件系統的需求,主要分爲如下幾個方面。後端
本部分討論gfs的整體架構,以及在此架構上須要考慮的一些問題。緩存
GFS的總體架構以下圖:微信
(圖片來源:gfs論文)網絡
GFS中有四類角色,分別是數據結構
在GFS chunkserver中,文件都是分紅固定大小的chunk來存儲的,每一個chunk經過全局惟一的64位的chunk handle來標識,chunk handle在chunk建立的時候由GFS master分配。GFS chunkserver把文件存儲在本地磁盤中,讀或寫的時候須要指定文件名和字節範圍,而後定位到對應的chunk。爲了保證數據的可靠性,一個chunk通常會在多臺GFS chunkserver上存儲,默認爲3份,但用戶也能夠根據本身的須要修改這個值。架構
GFS master管理全部的元數據信息,包括namespaces,訪問控制信息,文件到chunk的映射信息,以及chunk的地址信息(即chunk存放在哪臺GFS chunkserver上)。併發
GFS client是GFS應用端使用的API接口,client和GFS master交互來獲取元數據信息,可是全部和數據相關的信息都是直接和GFS chunkserver來交互的。app
Application爲使用gfs的應用,應用經過GFS client於gfs後端(GFS master和GFS chunkserver)打交道。
GFS架構中只有單個GFS master,這種架構的好處是設計和實現簡單,例如,實現負載均衡時能夠利用master上存儲的全局的信息來作決策。可是,在這種架構下,要避免的一個問題是,應用讀和寫請求時,要弱化GFS master的參與度,防止它成爲整個系統架構中的瓶頸。
從一個請求的流程來討論上面的問題。首先,應用把文件名和偏移量信息傳遞給GFS client,GFS client轉換成(文件名,chunk index)信息傳遞給GFS master,GFS master把(chunk handle, chunk位置信息)返回給客戶端,客戶端會把這個信息緩存起來,這樣,下次再讀這個chunk的時候,就不須要去GFS master拉取chunk位置信息了。
另外一方面,GFS支持在一個請求中同時讀取多個chunk的位置信息,這樣更進一步的減小了GFS client和GFS master的交互次數,避免GFS master成爲整個系統的瓶頸。
對於GFS來講,chunk size的默認大小是64MB,比通常文件系統的要大。
優勢
缺點
對於熱點問題,google給出的解決方案是應用層避免高頻地同時讀寫同一個chunk。還提出了一個可能的解決方案是,GFS client找其餘的GFS client來讀數據。
64MB應該是google得出的一個比較好的權衡優缺點的經驗值。
GFS master存儲三種metadata,包括文件和chunk namespace,文件到chunk的映射以及chunk的位置信息。這些metadata都是存儲在GFS master的內存中的。對於前兩種metadata,還會經過記操做日誌的方式持久化存儲,操做日誌會同步到包括GFS master在內的多臺機器上。GFS master不持久化存儲chunk的位置信息,每次GFS master重啓或者有新的GFS chunkserver加入時,GFS master會要求對應GFS chunkserver把chunk的位置信息彙報給它。
使用內存存儲metadata的好處是讀取metadata速度快,方便GFS master作一些全局掃描metadata相關信息的操做,例如負載均衡等。
可是,之內存存儲的的話,須要考慮的是GFS master的內存空間大小是否是整個系統能存儲的chunk數量的瓶頸所在。在GFS實際使用過程當中,這通常不會成爲限制所在,由於GFS中一個64MBchunk的metadata大小不超過64B,而且,對於大部分chunk來說都是使用的所有的空間的,只有文件的最後一個chunk會存儲在部分空間沒有使用,所以,GFS master的內存空間在實際上不多會成爲限制系統容量的因素。即便真的是現有的存儲文件的chunk數量超過了GFS master內存空間大小的限制,也能夠經過加內存的方式,來獲取內存存儲設計帶來的性能、可靠性等多種好處。
GFS master不持久化存儲chunk位置信息的緣由是,GFS chunkserver很容易出現宕機,重啓等行爲,這樣GFS master在每次發生這些事件的時候,都要修改持久化存儲裏面的位置信息的數據。
operation log的做用
怎麼存
operation log會存儲在GFS master和多臺遠程機器上,只有當operation log在GFS master和多臺遠程機器都寫入成功後,GFS master纔會向GFS client返回成功。爲了減小operation log在多臺機器落盤對吞吐量的影響,能夠將一批的operation log造成一個請求,而後寫入到GFS master和其餘遠程機器上。
check point
當operation log達到必定大小時,GFS master會作checkpoint,至關於把內存的B-Tree格式的信息dump到磁盤中。當master須要重啓時,能夠讀最近一次的checkpoint,而後replay它以後的operation log,加快恢復的時間。
作checkpoint的時候,GFS master會先切換到新的operation log,而後開新線程作checkpoint,因此,對新來的請求是基本是不會有影響的。
本部分討論GFS的系統交互流程。
GFS master對後續的數據流程是不作控制的,因此,須要一個機制來保證,全部副本是按照一樣的操做順序寫入對應的數據的。GFS採用lease方式來解決這個問題,GFS對一個chunk會選擇一個GFS chunkserver,發放lease,稱做primary,由primary chunkserver來控制寫入的順序。
Lease的過時時間默認是60s,能夠經過心跳信息來續時間,若是一個primary chunkserver是正常狀態的話,這個時間通常是無限續下去的。當primary chunkserver和GFS master心跳斷了後,GFS master也能夠方便的把其餘chunk副本所在的chunkserver設置成primary。
(圖片來源:gfs論文)
這裏,寫數據若是發生錯誤可能會產生不一致的狀況,會在consistency model中討論。
4.1中第三步的Data Flow採用的是pipe line方式,目標是爲了充分利用每臺機器的網絡帶寬。假設一臺機器總共有三個副本S1-S3。整個的Data Flow爲:
不斷重複上述流程,直到全部的chunkserver都收到client的全部數據。
以上述方式來傳送B字節數據到R個副本,並假設網絡吞吐量爲T,機器之間的時延爲L,那麼,整個數據的傳輸時間爲B/T+RL。
Append操做流程和寫差很少,主要區別在如下
這裏須要討論的是,若是append操做在部分副本失敗的狀況下,會發生什麼?
例如,寫操做要追加到S1-S3,可是,僅僅是S1,S2成功了,S3失敗了,GFS client會重試操做,假如第二次成功了,那麼S1,S2寫了兩次,S3寫了一次,目前的理解是GFS會先把失敗的記錄進行padding對齊到primary的記錄,而後再繼續append。
Snapshot的整個流程以下:
當snapshot操做完成後,client寫snapshot中涉及到的chunk C的流程以下:
(圖片來源:gfs論文)
GFS中consistent、defined的定義以下:
下面分析表格中出現的幾種狀況。
GFS用version來標記一個chunkserver掛掉的期間,是否有client進行了write或者append操做。每進行一次write或者append,version會增長。
須要考慮的點是client會緩存chunk的位置信息,有可能其中某些chunkserver已經掛掉又起來了,這個時候chunkserver的數據多是老的數據,讀到的數據是會不一致的。讀流程中,好像沒有看到要帶version信息來讀的。這個論文中沒看到避免的措施,目前尚未結果。
應用層須要採用的機制:用append而不是write,作checkpoint,writing self-validating和self-identifying records。具體地,以下:
GFS master的功能包括,namespace Management, Replica Placement,Chunk Creation,Re-replication and Rebalancing以及Garbage Collection。
每一個master操做都須要得到一系列的鎖。若是一個操做涉及到/d1/d2/.../dn/leaf,那麼須要得到/d1,/d1/d2,/d1/d2/.../dn的讀鎖,而後,根據操做類型,得到/d1/d2/.../dn/leaf的讀鎖或者寫鎖,其中leaf多是文件或者路徑。
一個例子,當/home/user被快照到/save/user的時候,/home/user/foo的建立是被禁止的。
對於快照,須要得到/home和/save的讀鎖,/home/user和/save/user的寫鎖。對於建立操做,會得到/home,/home/user的讀鎖,而後/home/user/foo的寫鎖。其中,/home/user的鎖產生衝突,/home/user/foo建立會被禁止。
這種加鎖機制的好處是對於同一個目錄下,能夠並行的操做文件,例如,同一個目錄下並行的建立文件。
GFS的Replica Placement的兩個目標:最大化數據可靠性和可用性,最大化網絡帶寬的使用率。所以,把每一個chunk的副本分散在不一樣的機架上,這樣一方面,能夠抵禦機架級的故障,另外一方面,能夠把讀寫數據的帶寬分配在機架級,重複利用多個機架的帶寬。
GFS在建立chunk的時候,選擇chunkserver時考慮的因素包括:
當一個chunk的副本數量少於預設定的數量時,須要作複製的操做,例如,chunkserver宕機,副本數據出錯,磁盤損壞,或者設定的副本數量增長。
chunk的複製的優先級是按照下面的因素來肯定的:
chunk複製的時候,選擇新chunkserver要考慮的點:
週期性地檢查副本分佈狀況,而後調整到更好的磁盤使用狀況和負載均衡。GFS master對於新加入的chunkserver,逐漸地遷移副本到上面,防止新chunkserver帶寬打滿。
在GFS刪除一個文件後,並不會立刻就對文件物理刪除,而是在後面的按期清理的過程當中才真正的刪除。
具體地,對於一個刪除操做,GFS僅僅是寫一條日誌記錄,而後把文件命名成一個對外部不可見的名稱,這個名稱會包含刪除的時間戳。GFS master會按期的掃描,當這些文件存在超過3天后,這些文件會從namespace中刪掉,而且內存的中metadata會被刪除。
在對chunk namespace的按期掃描時,會掃描到這些文件已經被刪除的chunk,而後會把metadata從磁盤中刪除。
在與chunkserver的heartbeat的交互過程當中,GFS master會把不在metadata中的chunk告訴chunkserver,而後chunkserver就能夠刪除這些chunk了。
採用這種方式刪除的好處:
壞處:
當一臺chunkserver掛掉的時候,有新的寫入操做到chunk副本,會致使chunkserve的數據不是最新的。
當master分配lease到一個chunk時,它會更新chunk version number,而後其餘的副本都會更新該值。這個操做是在返回給客戶端以前完成的,若是有一個chunkserver當前是宕機的,那麼它的version number就不會增長。當chunkserver重啓後,會彙報它的chunk以及version number,對於version number落後的chunk,master就認爲這個chunk的數據是落後的。
GFS master會把落後的chunk當垃圾來清理掉,而且不會把落後的chunkserver的位置信息傳給client。
備註:
1. GFS master把落後的chunk看成垃圾清理,那麼,是不是走re-replication的邏輯來生成新的副本呢?沒有,是走當即複製的邏輯。
爲了實現高可用性,GFS在經過兩方面來解決,一是fast recovery,二是replication
master和chunkserver都被設計成都能在秒級別重啓
每一個chunk在多個機架上有副本,副本數量由用戶來指定。當chunkserver不可用時,GFS master會自動的複製副本,保證副本數量和用戶指定的一致。
master的operation log和checkpoint都會複製到多臺機器上,要保證這些機器的寫都成功了,才認爲是成功。只有一臺master在來作garbage collection等後臺操做。當master掛掉後,它能在不少時間內重啓;當master所在的機器掛掉後,監控會在其餘具備operation log的機器上重啓啓動master。
新啓動的master只提供讀服務,由於可能在掛掉的一瞬間,有些日誌記錄到primary master上,而沒有記錄到secondary master上(這裏GFS沒有具體說同步的流程)。
每一個chunkserver都會經過checksum來驗證數據是否損壞的。
每一個chunk被分紅多個64KB的block,每一個block有32位的checksum,checksum在內存中和磁盤的log中都有記錄。
對於讀請求,chunkserver會檢查讀操做所涉及block的全部checksum值是否正確,若是有一個block的checksum不對,那麼會報錯給client和master。client這時會從其餘副本讀數據,而master會clone一個新副本,當新副本clone好後,master會刪除掉這個checksum出錯的副本。
主要是經過log,包括重要事件的log(chunkserver上下線),RPC請求,RPC響應等。
本部分主要討論大規模分佈式系統一書上,列出的關於gfs的一些問題,具體以下。
優勢
缺點
64MB應該是google得出的一個比較好的權衡優缺點的經驗值。
主要是爲了更有效地利用網絡帶寬。把數據流分開,能夠更好地優化數據流的網絡帶寬使用。
若是不分開,須要討論下。
padding出現場景:
重複記錄出現場景:
lease是gfs master把控制寫入順序的權限下放給chunkserver的機制,以減小gfs master在讀寫流程中的參與度,防止其成爲系統瓶頸。心跳是gfs master檢測chunkserver是否可用的標誌。
namespace、文件到chunk的映射以及chunk的位置信息
namespace採用的是B-Tree,對於名稱採用前綴壓縮的方法,節省空間;(文件名,chunk index)到chunk的映射,能夠經過hashmap;chunk到chunk的位置信息,能夠用multi_hashmap,由於是一對多的映射。
1GB/64MB = 1024 / 64 = 16。總共須要16 10000000 64 B = 10GB
主要是考慮CPU、內存、網絡和I/O,但如何綜合這些參數並計算仍是得看具體的場景,每部分的權重隨場景的不一樣而不一樣。
如何選擇chunkserver
如何避免同時遷移
經過限制單個chunkserver的clone操做的個數,以及clone使用的帶寬來限制,即從源chunkserver度數據的頻率作控制。
由於是過一會,因此假設chunk re-replication尚未執行,那麼在這期間,可能這臺chunkserver上有些chunk的數據已經處於落後狀態了,client讀數據的時候或者chunkserver按期掃描的時候會把這些狀態告訴給master,master告訴上線後的chunkserver從其餘機器複製該chunk,而後master會把這個chunk看成是垃圾清理掉。
對於沒有落後的chunk副本,能夠直接用於使用。
Snapshot的整個流程以下:
當snapshot操做完成後,client寫snapshot中涉及到的chunk C的流程以下:
chunkserver主要是存儲64KB block的checksum信息,須要由chunk+offset,可以快速定位到checksum,能夠用hashmap。
利用checksum機制,分讀和寫兩種狀況來討論:
chunkserver重啓後,會彙報chunk及其version number,master根據version number來判斷是否過時。若是過時了,那麼會作如下操做:
問題:若是chunkserver拷貝數據的過程過程當中,以前拷貝的數據備份又發生了變化,而後分爲兩種狀況討論:
PS:
本博客更新會在第一時間推送到微信公衆號,歡迎你們關注。