1. 程式人生 > >讀《The Google File System》

讀《The Google File System》

GFS特點:

1. 面向大規模資料密集型應用;

2. 可伸縮;

3. 分散式;

4. 災難冗餘;

5. 基於廉價硬體裝置;

6.元件失效是常態,不是意外;

設計背景:

1. 檔案巨大,因此I/O操作和Block尺寸都被重新考慮;

2. 絕大部分檔案的修改採用追加,而不是隨機寫入,因此資料追加操作對效能最為關鍵;

3. 工作負載:大規模流式讀取、小規模隨機讀取、大規模順序追加的寫操作;

4. 檔案通常用於“生產者-消費者”模式(上百個生產者同時寫入),因此要求最小的同步開銷;

5. 應用程式通常是批量處理資料,因此高效能的穩定網路頻寬遠比低延遲重要

GFS架構:


由GFS架構圖可以看出:

1. GFS由一個master和多個chunkserver組成,master管理檔案系統元資料,包括名字空間、訪問控制資訊、檔案與chunk的對映資訊,以及當前chunk的位置資訊,chunkserver儲存資料本身,底層仍然是基於linux檔案系統;

2. master傳送指令給各個chunkserver,chunkserver定時傳送心跳資訊給master,彙報自己的狀態;

3. 當客戶端想要訪問GFS的某個檔案時,首先根據chunk大小將檔案轉化成chunk索引,然後諮詢master,master將相應的chunk的位置資訊和標識返回給客戶端,之後客戶端以檔名和chunk索引為key快取這些元資料,並且直接與相應的chunkserver進行資料交換;

chunk尺寸:

chunk大小為64MB,且每個chunk副本都以普通linux檔案的形式儲存在chunkserver上,並使用惰性空間分配策略避免內部碎片,至於惰性空間分配是如何避免內部碎片的,見下圖。


大尺寸的chunk帶來的好處:

1. 減少客戶端和master的通訊,用更少的請求次數來獲取同一大小的檔案的chunk元資料;

2. 與chunkserver建立長時間的TCP連線,減輕網路負載;

3. 減少master需儲存的元資料數量;

壞處:

1. 小檔案造成的hotspot問題;

元資料:

master儲存3種主要型別的元資料:檔案和chunk的名稱空間、檔案和chunk的對應關係、每個chunk副本的存放地點。

所有元資料都儲存在master伺服器的記憶體中,並且master並不持久化儲存這些元資料,而是在每次啟動時輪詢chunkserver來獲取,之後通過心跳資訊進行更新。

操作日誌:

操作日誌是唯一被持久化儲存的元資料,記錄了名稱空間、檔案和chunk的對應關係。操作日誌被儲存在master伺服器的本地磁碟上,並複製到其他master伺服器。

checkpoint:

操作日誌增長到一定量時,會對系統狀態做一次checkpoint,並刪除之前的日誌檔案,該checkpoint檔案及之後的日誌檔案用於災難恢復。

資料一致性:

修改後的檔案region有三種狀態:

1. “已定義的(隱含一致性)”:所有客戶端都可以看到寫入的內容;

2. “一致的、未定義的”: 所有客戶端看到同樣的資料,但是看不到新寫入的資料;

3. “不一致的(同時也是未定義的)”: 不同客戶端在不同時間會看到不同的資料;

資料修改分為“寫入”和“記錄追加”,兩者的不同在於“寫入”指定了檔案偏移,而“追加”的檔案偏移由GFS計算決定

一致性保障措施:

1. 對chunk的所有副本修改操作順序一致;

2. 維護chunk版本號;

3. master伺服器與chunkserver定期“握手”,並使用checksum來校驗資料;

系統互動:

原則是最小化所有操作和master節點的互動。

資料變更操作採用租約(lease)機制,如圖所示。


step1. client向master詢問持有租約的chunkserver及其副本位置;

step2. master將主chunk的識別符號及其副本位置返回給client;

step3. clien將資料推送到所有副本,這裡採用線性集中推送,而非拓撲分散推送,即每個chunkserver都選擇一個離自己最近的、還沒有接收到資料的chunkserver進行推送,這是為了讓每臺機器的出口頻寬以最快速度傳輸資料而不用在多個接收者間分配頻寬;

step4. 當所有副本都收到資料後,client傳送寫請求到主chunkserver,主chunkserver為操作分配連續的序列號(正是這些序列號保證了所有chunk副本以同樣的順序進行操作),主chunkserver按順序執行這些操作;

step5. 主chunk將寫請求傳遞到所有二級副本,每個二級副本按主chunk分配的序列號執行操作;

step6. 所有二級副本回復主chunk操作已完成;

step7. 主chunkserver回覆client操作已完成;

記錄追加:

記錄追加是原子性的,GFS保證資料作為一個整體原子至少被寫入一次,任何一個chunk副本操作失敗都會導致client重新操作,記錄追加的資料大小嚴格控制在chunk最大尺寸的1/4,以控制資料碎片數量。

快照:

快照以很低的開銷完成對一個檔案或者目錄樹的拷貝,使用者可以使用快照迅速地建立一個巨大資料集的分支拷貝,或是在做實驗性的資料操作之前,使用快照備份當前狀態用以回滾。

快照採用copy on write(寫入時拷貝)技術,根據維基百科的解釋,COW是一種用於程式設計最佳化的策略,當有多個呼叫者同時請求同一個資源時,他們會共同取得指向該資源的指標,只有當某個呼叫者嘗試修改該資源時,系統才會真正複製一個副本給該呼叫者(寫入時才複製)以避免被修改的資源被直接察覺到,該過程對其他呼叫者都是透明的,該策略的主要優點是如果呼叫者沒有嘗試修改資源,則系統不會建立資源的副本。

對應到GFS,快照請求由使用者發出,當master接收到一個快照請求時,它首先取消快照檔案涉及的所有chunk的租約,當有多個client同時請求該檔案時(此時還沒有寫請求),master將同一份檔案的元資料傳送給所有client,直到第一次某個client發出對該檔案(中某個chunk C)的寫請求時,由於client向master詢問持有租約的chunkserver及其副本位置,此時master發現該chunk C的引用計數超過了1,master要求每個擁有chunk C 當前副本的chunkserver建立一個新的chunk C'(本地建立),master與新的chunk C'的一個副本建立租約,並把新chunk C'的租約資訊返回給client,之後所有修改操作都是針對該新chunk C‘。

master節點的職責

master節點的職責包括:名稱空間管理和鎖,副本的位置,建立、重新複製、重新負載均衡,垃圾回收,過期失效的副本檢測。

1. 名稱空間管理和鎖:GFS的名稱空間是一個全路徑和元資料對映關係的查詢表,在儲存名稱空間的屬性結構上,每個節點都有一個關聯的讀寫鎖,當操作涉及/di/d2/.../dn/leaf時,首先要獲得/d1, /d1/d2, ..., /d1/d2/.../dn的讀鎖,還要獲得/d1/d2/.../dn/leaf的讀寫鎖,這種方案支援對同一目錄的並行操作。

2. 副本的位置: 副本位置的選擇策略服務兩大目標,即最大化資料可靠性和可用性,最大化網路頻寬利用率。因此,不僅要在多臺機器上分別儲存副本,還要在多個機架間分佈儲存chunk副本。

3. chunk建立,重新複製和重新負載均衡:

1)建立位置選擇因素:a. 在低於平均硬碟使用率的chunk伺服器上儲存;b. 限制在每個chunkserver上“最近”的chunk建立操作的次數;c. 分佈在多個機架之間;

2)重新複製位置選擇因素:首先對所有需要複製的chunk設定優先順序,優先順序考慮到三個因素:a. 優先複製現有副本與複製因數相差較大的chunk;b. 優先複製活躍檔案的chunk;c. 優先複製會阻塞client程式處理流程的chunk;然後位置選擇與1)相同;

3)週期性重新負載均衡位置選擇因素:與1)相同;

4. 垃圾回收:惰性

5. 過期失效的副本檢測: 利用chunk的版本號,每次master節點和chunk簽訂一個新的租約就增加chunk的版本號,若某個副本失效,其chunk版本號不會增加,master在例行垃圾回收是發現並移除過期失效的副本。

高可用性機制:快速恢復、複製

資料完整性:每個chunkserver獨立維護自己的checksum