摘要:本文主要闡述關(guān)于分布式文件系統(tǒng)GFS,它是一個可擴展的分布式文件系統(tǒng),用于大型的、分布式的、對大量數(shù)據(jù)進行訪問的應(yīng)用。通過詳細介紹其一致性模塊以及讀寫流程,針對GFS的大塊的邏輯和設(shè)計理念及相關(guān)要點都進行了詳細的分析。
關(guān)鍵詞:云儲存系統(tǒng);GFS系統(tǒng)架構(gòu);設(shè)計策略;
一、GFS設(shè)計思路
1.組件/機器失效
GFS包括幾百甚至幾千臺普通的廉價設(shè)備組裝的存儲機器,同時被相當數(shù)量的客戶機訪問。GFS組件的數(shù)量和質(zhì)量導致在事實上,任何給定時間內(nèi)都有可能發(fā)生某些組件無法工作,某些組件無法從它們目前的失效狀態(tài)中恢復(fù)。例如谷歌遇到過各種各樣的問題,比如應(yīng)用程序bug、操作系統(tǒng)的bug、人為失誤,甚至還有硬盤、內(nèi)存、連接器、網(wǎng)絡(luò)以及電源失效等造成的問題。所以,持續(xù)的監(jiān)控、錯誤偵測、災(zāi)難冗余以及自動恢復(fù)的機制必須集成在GFS中。
2.谷歌處理的文件都非常巨大。(大數(shù)據(jù)):
這點跟NEFS的場景既有相似性又不完全一致,NEFS上層對接的是NOS對象存儲,基本都是大量的小文件(100MB以下),總體量比較大,對象個數(shù)比較多,因此也需要考慮元數(shù)據(jù)管理的成本,因此NEFS采用了小文件合并的設(shè)計思路(不詳細展開)。
谷歌系統(tǒng)中數(shù)GB的文件非常普遍。每個文件通常都包含許多應(yīng)用程序?qū)ο?,比如web文檔。當我們經(jīng)常需要處理快速增長的、并且由數(shù)億個對象構(gòu)成的、數(shù)以TB的數(shù)據(jù)集時,采用管理數(shù)億個KB大小的小文件的方式是非常不明智的,盡管有些文件系統(tǒng)支持這樣的管理方式。因此,設(shè)計的假設(shè)條件和參數(shù),比如I/O操作和Block的尺寸都需要重新考慮。
3.絕大部分文件的修改是采用在文件尾部追加數(shù)據(jù),而不是覆蓋原有數(shù)據(jù)的方式。(讀寫模型:順序?qū)懀蟛糠猪樞蜃x,小部分隨機讀):
對文件的隨機寫入操作在實際中幾乎不存在。一旦寫完之后,對文件的操作就只有讀,而且通常是按順序讀。大量的數(shù)據(jù)符合這些特性,比如:數(shù)據(jù)分析程序掃描的超大的數(shù)據(jù)集;正在運行的應(yīng)用程序生成的連續(xù)的數(shù)據(jù)流;存檔的數(shù)據(jù);由一臺機器生成、另外一臺機器處理的中間數(shù)據(jù),這些中間數(shù)據(jù)的處理可能是同時進行的、也可能是后續(xù)才處理的。對于這種針對海量文件的訪問模式,客戶端對數(shù)據(jù)塊緩存是沒有意義的,數(shù)據(jù)的追加操作是性能優(yōu)化和原子性保證的主要考量因素。
4.應(yīng)用程序和文件系統(tǒng)API協(xié)同設(shè)計,簡化對GFS的要求(靈活性):
例如一致性模型要求放松了,這樣就減輕了文件系統(tǒng)對應(yīng)用程序的苛刻要求,大大簡化了GFS的設(shè)計。并且引入了原子性的記錄追加操作,從而保證多個客戶端能夠同時進行追加操作,不需要額外的同步操作來保證數(shù)據(jù)的一致性。
二、GFS接口:
GFS提供了一套類似傳統(tǒng)文件系統(tǒng)的API接口函數(shù),文件以分層目錄的形式組織,用路徑名來標識。GFS支持常用的操作,如創(chuàng)建新文件、刪除文件、打開文件、關(guān)閉文件、讀和寫文件。但是要理解一點:文件塊被存儲在linux硬盤上,GFS只是一個管理器而已,這些文件操作API也只是個對這些抽象文件的管理而已。也就是說GFS層級比底層文件系統(tǒng)以及虛擬文件系統(tǒng)層次要高。注:這點跟NEFS也比較像,NEFS也是對文件粒度進行管理的,而不是針對塊設(shè)備,因此也是在底層文件系統(tǒng)及虛擬文件系統(tǒng)之上。
四、GFS設(shè)計架構(gòu):
使用論文中的原圖如下:如圖所示,GFS主要由以下三個系統(tǒng)模塊組成:Master:管理元數(shù)據(jù)、整體協(xié)調(diào)系統(tǒng)活動。·ChunkServer:存儲維護數(shù)據(jù)塊(Chunk),讀寫文件數(shù)據(jù)。·Client:向Master請求元數(shù)據(jù),并根據(jù)元數(shù)據(jù)訪問對應(yīng)ChunkServer的Chunk。
三、GFS設(shè)計要點:
(1)chunk機制
chunk是GFS中管理數(shù)據(jù)的最小單元(數(shù)據(jù)塊),每一個chunk被一個64位的handle唯一標識,chunk被當做普通的文件存儲在linux系統(tǒng)中。每個chunk至少會在另一個chunkserver上有備份,而默認會為每個chunk做三個備份。chunk大小默認為64MB,比一般的文件系統(tǒng)的4kb的塊要大的多得多。Chunkserver一般不會緩存數(shù)據(jù),因為chunk都是存儲在本地,故而linux已經(jīng)將經(jīng)常被訪問的數(shù)據(jù)緩存在內(nèi)存中了。
chunk塊設(shè)置比較大(一般文件系統(tǒng)的塊為4kb)的優(yōu)缺點如下:
優(yōu)點:
1.減少元數(shù)據(jù)量,方便客戶端預(yù)讀緩存(filename+chunkindex->chunkhandle+chunkserverlocation),減少客戶端訪問的次數(shù),減少master負載。
2.減少元數(shù)據(jù)量,master可以將元數(shù)據(jù)放在內(nèi)存中。
3.客戶端取一次元數(shù)據(jù)就能讀到更多數(shù)據(jù),減少客戶端訪問不同chunkserver建立tcp連接的次數(shù),從而減少網(wǎng)絡(luò)負載。
缺點:
1.對于小文件的場景,容易產(chǎn)生數(shù)據(jù)碎片。
2.小文件占用chunk少,對小文件頻繁訪問會集中在少數(shù)chunkserver上,從而產(chǎn)生小文件訪問熱點(這個問題在后續(xù)的可靠性篇章中有相關(guān)的解決方案)。
(2)元數(shù)據(jù)管理
系統(tǒng)中三種元數(shù)據(jù)類型:·文件和chunk的名稱(命名空間)。文件和chunk之間的映射關(guān)系,比如說每個文件是由哪些chunk共同組成。每個chunk備份的位置。命名空間、文件和Chunk的對應(yīng)關(guān)系的存儲方式:內(nèi)存:真實數(shù)據(jù);磁盤:定期Checkpoint(壓縮B樹)和上次CheckPoint后的操作日志;多機備份:Checkpoint文件和操作日志。Chunk位置信息的存儲方式:內(nèi)存:真實數(shù)據(jù)磁盤:不持久存儲系統(tǒng)啟動和新Chunk服務(wù)器加入時從Chunk服務(wù)器獲取。避免了Master與ChunkServer之間的數(shù)據(jù)同步,只有Chunk服務(wù)器才能最終確定Chunk是否在它的硬盤上。
(3)Master單一性
單一的Master節(jié)點的策略大大簡化了FGS的設(shè)計。單一的Master節(jié)點可以通過全局的信息精確定位Chunk的位置以及進行復(fù)制決策。針對master宕機的處理和恢復(fù)在后續(xù)的高可用篇中詳細介紹。
(4)操作日志
操作日志包含了關(guān)鍵的元數(shù)據(jù)變更歷史記錄。這對GFS非常重要。這不僅僅是因為操作日志是元數(shù)據(jù)唯一的持久化存儲記錄,它也作為判斷同步操作順序的邏輯時間基線。文件和Chunk,連同它們的版本(可以看做是更新次數(shù),以判斷chunk是否過期,低版本的認為過期),都由它們創(chuàng)建的邏輯時間唯一的、永久的標識。操作日志和chunk數(shù)據(jù)一樣,都需要復(fù)制到多臺機器,使用多副本保存。
租約(lease)機制主要是為了保持多個副本間變更順序一致性的。Master節(jié)點為Chunk的一個副本建立一個租約,我們把這個副本叫做主Chunk。主Chunk對Chunk的所有更改操作進行序列化。所有的副本都遵從這個序列進行修改操作。因此,修改操作全局的順序首先由Master節(jié)點選擇的租約的順序決定,然后由租約中主Chunk分配的序列號決定。設(shè)計租約機制的目的是為了最小化Master節(jié)點的管理負擔。租約的初始超時設(shè)置為60秒。不過,只Chunk被修改了,主Chunk就可以申請更長的租期,通常會得到Master節(jié)點的確認并收到租約延長的時間。這些租約延長請求和批準的信息通常都是附加在Master節(jié)點和Chunk服務(wù)器之間的心跳消息中來傳遞。有時Master節(jié)點會試圖提前取消租約(例如,Master節(jié)點想取消在一個已經(jīng)被改名的文件上的修改操作)。即使Master節(jié)點和主Chunk失去聯(lián)系,它仍然可以安全地在舊的租約到期后和另外一個Chunk副本簽訂新的租約。寫入流程如下,例如有1個主副本,2個從副本的情況:
客戶機向Master節(jié)點詢問哪一個Chunk服務(wù)器持有當前的租約,以及其它副本的位置。如果沒有一個Chunk持有租約,Master節(jié)點就選擇其中一個副本建立一個租約(這個步驟在圖上沒有顯示)。Master節(jié)點將主Chunk的標識符以及其它副本(又稱為secondary副本、二級副本)的位置返回給客戶機??蛻魴C緩存這些數(shù)據(jù)以便后續(xù)的操作。只有在主Chunk不可用,或者主Chunk回復(fù)信息表明它已不再持有租約的時候,客戶機才需要重新跟Master節(jié)點聯(lián)系。
客戶機把數(shù)據(jù)推送到所有的副本上。客戶機可以以任意的順序推送數(shù)據(jù)。Chunk服務(wù)器接收到數(shù)據(jù)并保存在它的內(nèi)部LRU緩存中,一直到數(shù)據(jù)被使用或者過期交換出去。由于數(shù)據(jù)流的網(wǎng)絡(luò)傳輸負載非常高,通過分離數(shù)據(jù)流和控制流,我們可以基于網(wǎng)絡(luò)拓撲情況對數(shù)據(jù)流進行規(guī)劃,提高系統(tǒng)性能,而不用去理會哪個Chunk服務(wù)器保存了主Chunk。
(1)當所有的副本都確認接收到了數(shù)據(jù),客戶機發(fā)送寫請求到主Chunk服務(wù)器。這個請求標識了早前推送到所有副本的數(shù)據(jù)。主Chunk為接收到的所有操作分配連續(xù)的序列號,這些操作可能來自不同的客戶機,序列號保證了操作順序執(zhí)行。它以序列號的順序把操作應(yīng)用到它自己的本地狀態(tài)中(也就是在本地執(zhí)行這些操作,這句話按字面翻譯有點費解,也許應(yīng)該翻譯為“它順序執(zhí)行這些操作,并更新自己的狀態(tài)”)。
(2)主Chunk把寫請求傳遞到所有的二級副本。每個二級副本依照主Chunk分配的序列號以相同的順序執(zhí)行這些操作。
(3)所有的二級副本回復(fù)主Chunk,它們已經(jīng)完成了操作。
(4)主Chunk服務(wù)器(即主Chunk所在的Chunk服務(wù)器)回復(fù)客戶機。
任何副本產(chǎn)生的任何錯誤都會返回給客戶機。在出現(xiàn)錯誤的情況下,寫入操作可能在主Chunk和一些二級副本執(zhí)行成功。(如果操作在主Chunk上失敗了,操作就不會被分配序列號,也不會被傳遞。)客戶端的請求被確認為失敗,被修改的region處于不一致的狀態(tài)。我們的客戶機代碼通過重復(fù)執(zhí)行失敗的操作來處理這樣的錯誤。
在從頭開始重復(fù)執(zhí)行之前,客戶機會先從步驟(3)到步驟(7)做幾次嘗試。如果應(yīng)用程序一次寫入的數(shù)據(jù)量很大,或者數(shù)據(jù)跨越了多個Chunk,GFS客戶端代碼會把它們分成多個寫操作。這些操作都遵循前面描述的控制流程,但是可能會被其它客戶機上同時進行的操作打斷或者覆蓋。因此,共享的文件region的尾部可能包含來自不同客戶機的數(shù)據(jù)片段,盡管如此,由于這些分解后的寫入操作在所有的副本上都以相同的順序執(zhí)行完成,Chunk的所有副本都是一致的。這使文件region處于上一節(jié)描述的一致的、但是未定義的狀態(tài)。讀取流程可以再看一下設(shè)計架構(gòu)圖中的conrol和data流。
(1)GFSclient將服務(wù)所要讀取的文件名與byteoffset,根據(jù)系統(tǒng)chunk大小,換算成文件的chunkindex,即文件數(shù)據(jù)所處的第幾個chunk。
(2)將filename與chunkindex傳給master。
(3)Master返回給client元數(shù)據(jù)信息(包含chunkhandle與實際存儲的chunkserverlocation)。然后client獲取到該信息,作為key值與filename+chunkindex緩存起來。
(4)Client根據(jù)這些元數(shù)據(jù)信息,直接對chunkserver發(fā)出讀請求。對于三副本而言(一份chunk存儲在三臺不同的chunkserver),client選擇離自己最近的chunkserver(網(wǎng)絡(luò)?),通過之前獲取的元數(shù)據(jù)信息找到需要讀的chunk位置以及下一個chunk位置。如果緩存的元數(shù)據(jù)信息已過期,則需要重新向master去獲取一遍。
(5)Chunkserver返回給client要讀的數(shù)據(jù)信息。
結(jié)語
GFS的設(shè)計思路決定了它的主體框架及設(shè)計要點。針對于GFS大部分都是順序讀取的場景來說,不需要做進一步的優(yōu)化。針對數(shù)據(jù)追加的優(yōu)化才是針對順序?qū)懙哪繕藞鼍斑M行的好的優(yōu)化設(shè)計點。NEFS的目標場景跟GFS有一定的差別,NEFS上層對接的是NOS對象存儲,基本都是大量的小文件(100MB以下),總體量比較大,對象個數(shù)比較多。而且大部分是順序?qū)懀S機讀場景,因此目標場景不一致導致結(jié)構(gòu)和設(shè)計會有一定的差異。
參考文獻
[1] Thomas Anderson, Michael Dahlin, Jeanna Neefe, David Patterson, Drew Roselli, and Randolph Wang. Serverless networkfil e systems. In Proceedings of the 15th ACM Symposium on Operating System Principles, pages 109–126, Copper Mountain Resort, Colorado, December 1995.
[2] Remzi H. Arpaci-Dusseau, Eric Anderson, Noah Treuhaft, David E. Culler, Joseph M. Hellerstein, David Patterson, and Kathy Yelick. Cluster I/O with River: Making the fast case common. In Proceedings of the Sixth Workshop on Input/Output in Parallel and Distributed Systems (IOPADS 99), pages 10–22, Atlanta, Georgia, May 1999.
[3] Luis-Felipe Cabrera and Darrell D. E. Long. Swift: Using distributed disks triping to provide high I/O data rates. Computer Systems, 4(4):405–436, 1991.
作者簡介
孫偉(1981-),男,漢族,內(nèi)蒙古察呼倫貝爾人,集寧師范學院計算機學院講師,工程碩士,研究方向:軟件工程。