天天看點

GFS論文整理(一)

摘要:

    我們設計并實作了GFS:一個高擴充性,适用于資料密集型應用的分布式檔案系統。運作在廉價的商用伺服器上,它提供了容錯能力,它能夠在大量用戶端請求時提供較好的整體性能。

    當享用衆多具有同樣上述目的的分布式檔案系統時,我們的設計驅動力來對應用的工作量和技術環境,無論是目前還是預期,也折射出與早期的檔案系統的背離。這些引導我們重新檢測傳統選擇或者探索一個不同的設計方式。

    這種檔案系統比較成功的滿足了我們的存儲需要,它作為一個資料的存儲和處理平台被廣泛的應用在google,作為研究和開發大資料集合資料。最大的分布式資料能夠提供成千上萬TB的資料存儲,存儲在無數個硬碟和機器上,同時可以支援大量的用戶端并發調用。

簡介:

    我們已經設計和實作了GFS來滿足在大資料處理方面快速增長的需要,GFS  和先前的檔案系統,具

有相同的目标:擴充性,可用性,可靠性。

    首先,元件故障是一個平常的事情而不是異常。GFS系統可能會有上千台機器組成,而且也會有相當級别的用戶端(調用),元件的數量和品質實質上決定了某時的可用性和資料的恢複能力,我們遇到過很多問題,它們是有多方面原因造成的,例如應用的bug,作業系統的bug,人為的錯誤,硬碟問題,記憶體,網絡,電力供應等等。是以,持續的監控,錯誤檢測,容錯,自動恢複這些特性将被融入整個系統。

    再者,對于傳統的标準而言,這些檔案将是很龐大的,數GB的檔案是很常見的。每個檔案會包含許多像web文檔這樣的資料,當我們定期的去處理這些數TB的這種特性的資料. 快速增長的資料集合時,會發現管理它們将是一件很棘手的事情,盡管檔案系統能夠支援它。是以,設計假設和IO操作的參數/block尺寸等,需要重新對待。

    第三,大部分檔案資料的變更是通過append(追加)而不是重寫的方式,在一個檔案内随機寫操作幾乎是不存在的。一旦寫入,那麼這個檔案隻讀,并且經常是有序讀。有些能夠構成大倉儲,資料分析程式能夠掃描。有些或許是應用程式持續産生的資料流。有些或許是檔案資料,有些或許是供其他機器處理的中間資料(實時或者稍後)。針對這些特定的大檔案存儲方式,appending成為了性能優化和原子性保證的焦點,同時在用戶端緩存資料的方式失去了優勢。

    第四,聯合設計應用和檔案系統api,通過增加我們的靈活性,使整個系統收益。例如,我們放松了GFS的資料一緻性模型,大大簡化了檔案系統的設計,并且沒有給應用系統增加額外的負擔。我們引入了原子性append操作,可以讓多個用戶端操作并發的append一個檔案,在它們之間卻無需額外的同步。

    多個GFS分布式環境應用與不同的目的,最大的一個超過1000個存儲節點,超過300TB的硬碟存儲,并且被無數個用戶端大量的通路着。

設計總覽:

    在設計這個檔案系統時,預期的設想使我們遇到了很多挑戰。我們展示以下GFS設計的關鍵點。

    1)系統建構在廉價的商業伺服器上,且它們會經常出現故障。系統需要持續的自我監測,檢測/容忍/并能在故障時及時修複。

    2)系統存儲适當量的大檔案,我們預期有數百萬的檔案,檔案在100M左右,當然GB級别的檔案也是很常有的并且需要被高效的管理。小檔案也必須支援,但是我們可能不會優化它們(意思是,針對大檔案存儲,是優化的重點)

    3)主要包括2種方式的read:大資料流read和小随即讀。在大資料流讀中,個别的操作是讀取上百KB,1MB或者更大的讀取将是很常見的。同一用戶端的連續操作經常會讀取一個檔案鄰近的region。小随即讀通常會在任意的offset讀取幾個KB的資料。對于性能敏感的應用經常批量和排序這些small reads,穩步向前操作檔案,而不是來回移動。(順序讀取)

    4)還會有很多大資料/順序寫操作,通過向檔案append的方式進行。我們的檔案經常作為producer-consumer(生産者-消費者)隊列或者多路合并。多個生産者運作在一台機器上,将會并發的append檔案。原子性與最小同步開銷是必不可少的。

    5)持續的高帶寬比低延遲更加重要。我們的大部分目标應用,要求對大量資料的處理速度,而不是個别read或者write上嚴格的響應時間。

    GFS提供了一些類似的檔案系統接口,雖然它沒有按照規範的API例如POSIX。檔案通過目錄層級組織起來,通過路徑名稱來識别。我們支援常用的操作如create/delete,open,close,read,write。

    此外,GFS具有snapshot(快照)和記錄追加(record append)操作。snapshot以較少的開支建立一個檔案或者目錄樹(directory tree)的copy。Record append允許多個用戶端并發的在同一個檔案中追加資料,同時尚可確定每個client append操作的原子性,這對實作多路合并結果(multi-way merge)很有用,producer-consumer隊列可以被多個用戶端同時append而無需多餘的lock。我們發現這些檔案特性在建構大規模分布式應用時具有重要價值。

架構:

    一個GFS分布式環境,有一個master和多個chunkserver構成,它可以被多個用戶端通路。這些(server,client)通常是一些運作着使用者級别的服務程式的商用linux機器。chunkserver和client運作在同一台機器也是很容易的,當然前提是機器的資源是允許使用的,同時較低的可用性是可以接受的。

    檔案被分成固定尺寸的chunks,每個chunk通過一個全局不變的64位chunk handle來辨別,這個chunk handle是chunk建立時master機器配置設定的。chunkserver以linux檔案的方式把chunks存儲在本地磁盤上,對于read/write資料時将會操作由chunk handle和位元組區間(byte range)指定的chunk。為了可用性,每個chunk被複制分散在多台機器上;預設情況下,每個chunk的replicas有3個,當然使用者可以指定不同的file namespace中的region具有不同的replication的級别。

    Master機器儲存了檔案系統的所有metadata(中繼資料),包括namespace(命名空間),通路權限控制,檔案與chunks的影射關系,還有目前chunks的位置。它(master)也控制系統範圍内的activities(活動),例如chunk lease(契約)管理,孤立(失效)chunk的回收,chunkserver間 chunk的遷移(migration)。master會間歇性的與每個chunkserver通訊,在heartbeat messages(心跳消息)中發送指令和收集chunkserver的狀态。

    GFS用戶端程式(client code)會被引入到實作檔案系統API的應用中,應用程式通過client code與master和chunkserver互動,來實作對資料的read和write。Client與master互動進行metadata方面的操作,但是實際資料的互動将直接與chunkserver通信。我們沒有提供POSIX  API,是以将不需要挂載到linux vnode層。

    client和chunkserver均不會緩存檔案資料。client緩存收益甚微,因為大部分應用stream through龐大的檔案或者加工的資料的太大而無法緩存。沒有緩存,意味着将無需考慮緩存資料同步的因素,這簡化了用戶端以及整個系統的設計。chunkservers也無需緩存檔案資料,因為chunks存儲在本地檔案檔案中,linux buffer cache已經把這些頻繁通路的資料儲存了在記憶體中。

單Master:

    單Master很大程度上簡化了我們的設計,使得master能夠使用全局知識(global knowledge)來做複雜的chunk置放和複制方面的決策。此外,我們必須最小化對master的調用,是以master不會成為cluster的瓶頸。client從不通過master去read和write檔案資料,相反,client會詢問master 去連接配接哪個chunkserver,client會緩存這些資訊,接下來操作就是client和chunkserver直接互動。

GFS論文整理(一)

    讓我們解釋一下一個簡單的read操作的互動過程,參見圖1.首先,使用固定chunk size,client将應用指定的檔案名稱和byte offset轉換成檔案系統的一個chunk索引(filename 和byte offset可以最終确定為某個file中的特定chunk資訊)。然後,它(client)向master發送一個包含檔案明和chunk索引的請求,master響應給client相應的chunk handle和replicas的位置。Client使用fileName和chunk index作為key來緩存這些資訊。

    此後client向其中一個replicas發送請求,多數情況下是最近的一個replicas。請求指定了chunk handle和此chunk中的byte range。後續對同一個chunk 的reads将無需與master互動,直到cache過期或者file被重新打開。事實上,client通常會在一次master互動中詢問多個chunk的情況,避免了以後client-master的多次互動,事實上也不會帶來額外的性能開支。

Chunk Size:

    chunk size是一個關鍵的設計參數,我們選擇了64MB,這個值通常比檔案系統的block size要大很多。每個chunk replicas都是作為一個普通的linux檔案存儲在server上,并且會在需要的時候擴充它。延遲空間配置設定政策避免了對存儲空間的浪費(内部碎片),也許最大的反對點就是這種大尺寸的chunk。

    一個大尺寸的chunk你能夠提供一些重要的優勢。首先,它降低了client與master互動的次數,因為read和write同一個chunk隻需要初始時與master一次互動擷取chunk位置即可。它的降低,對于我們的workloads來說特别顯著,因為應用大多數是順序的read和write一個大檔案。即使一些小的随即度操作(small random reads),用戶端能夠适當的緩存數TB資料中所有的chunk位置資訊。再者,對于一個較大的chunk,用戶端能夠運作大量操作在此指定的chunk上,它能夠通過保持現有的TCP連接配接(client-->chunkserver的連接配接)來降低網絡開銷。第三,它(大尺寸chunk設計)降低了master中metadata的存儲尺寸,這就允許我們把metadata存儲在記憶體中,也會帶來其他的優勢(接下來讨論)。

    另一個方面開說,大尺寸chunk,即使采用延遲空間配置設定,也會有它的缺點。小檔案包含少量的chunk,或許隻有一個。在多個用戶端通路同一個檔案時,存儲這些chunk的chunkserver可能成為熱點(hot spots)。實踐中,hot spots還不是一個主要的問題,因為我們的應用大多數情況下是順序read一個多chunks的大檔案。

    可是,在hotspots尚未發展時,GFS開始使用的是批量隊列系統:一個可執行檔案作為一個single-chunk的檔案被寫入到GFS,然後同時在多個機器上啟動。存儲這個可執行檔案(executeable)的幾個chunkservers在數個請求同時通路時可能會過載。我們解決了這個問題,通過使用更高的複制因子(higher replication factor)存儲這個執行檔案,使被處理隊列系統錯開應用啟動的時間。在這種情況下,一個潛在的解決辦法就是允許用戶端可以從其他用戶端讀取資料。(事實上此解決辦法是不可取的)

Metadata:

    master存儲3個主要類型的metadata:file and chunk namespaces(檔案和chunk的命名空間),the mapping from files to chunks(檔案與chunk影射關系),the location of each chunks‘ replicas(chunk replicas位置)。這些中繼資料儲存在master的記憶體中。前2種類型的metadata(namespaces ,file-chunk mapping)也會通過記錄變更的方式持久存儲一個記錄檔檔案中(operation log),這個記錄檔檔案存儲在master的本地磁盤并且被replicated在其他的遠端機器上(和chunk的機制一樣)。有了日志,我們就能夠簡單而且可靠的去更新master的狀态,無需擔心master機器crash所帶來的不一緻問題。

    因為metadata存儲在記憶體中,master操作将是很迅速的。此外,對與master背景間歇性掃描整個state也将是很簡單和高效的。間歇性掃描,是用來實作chunk回收/重複制故障機器的chunk/chunk遷移(負載均衡,和跨chunkserver磁盤空間使用率)。

    這種記憶體存儲方式,有一個潛在的顧慮是chunk的數量,因為整個系統的容量會受到master記憶體大小的限制。在實踐中,這似乎不是一個很嚴重的限制。每個64MB的chunk,在master中之需要64B的metadata存儲,大部分chunk都是滿的(full)因為通常一個檔案會包含多個chunks,隻有最後一個(chunk)是可以被filled(填充資料)。類似,file namespace資料通常隻需要少于64B的資料,因為它(master)存儲file names會進行字首壓縮。

    如果需要支撐更大的檔案系統,那麼給master機器增加記憶體也是很簡單和廉價的。是以将metadata記憶體儲存,可以獲得靈活性/性能/可用性/簡易性等。

Chunk位置:

    master不會持久存儲chunkserver所持有的replicas資訊,它(master)僅僅是在啟動後去各個chuankserver上poll這些資料,然後會保持自己所持有chunk資訊的更新,因為它控制了所有chunk位置配置設定,以及使用定期的heartbeat消息監控chunkserver的狀态。

    我們起初嘗試過在master上持久存儲chunk位置資訊,但是我們覺得master啟動時從chunkserver請求這些資料然後間歇性同步的設計更加簡單。這樣可以避免一些問題:保持master和chunkservers的同步(chunkserver的加入,離群),修改名稱失敗,重新開機等等。在一個具有數百台機器的分布式環境中,這些情況還是會經常發生的。

    可以從另一個方向來認識這種設計,chunkserver上是否持有chunk,chunkserver具有最終決定權。那就沒有必要在master中再持久存儲一份視圖資料,而且chunkserver的一些error會導緻chunk資訊的丢失(硬碟損壞或者不可用),甚至有的操作會重命名chunkserver。

GFS論文整理(二):[http://shift-alt-ctrl.iteye.com/blog/1842286]

GFS論文整理(三):[http://shift-alt-ctrl.iteye.com/blog/1842509]

GFS論文整理(四):[http://shift-alt-ctrl.iteye.com/blog/1842510]

繼續閱讀