日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

《The Google File System》gfs论文翻译

發(fā)布時間:2024/1/18 编程问答 70 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《The Google File System》gfs论文翻译 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

作者

Sanjay Ghemawat, Howard Gobioff, and Shun-Tak Leung

Google

摘要

GFS(Google File System)是由我們設(shè)計并實現(xiàn)的為大規(guī)模分布式數(shù)據(jù)密集型應(yīng)用程序設(shè)計的可伸縮(scalable)的分布式文件系統(tǒng)。GFS為在廉價商用設(shè)備上運行提供了容錯能力,并可以在有大量客戶端的情況下提供較高的整體性能。

GFS的設(shè)計來自于我們對我們的應(yīng)用負載與技術(shù)環(huán)境的觀察。雖然GFS與過去的分布式文件系統(tǒng)有著共同的目標,但是根據(jù)我們的觀察,我們的應(yīng)用負載和技術(shù)環(huán)境與過去的分布式系統(tǒng)所做的假設(shè)有明顯的不同。這讓我們重新審視了傳統(tǒng)的選擇并去探索完全不同的設(shè)計。

GFS很好地滿足了我們的存儲需求。GFS在Google被廣泛地作為存儲平臺部署,用于生成、處理我們服務(wù)所使用的數(shù)據(jù)或用于需要大規(guī)模數(shù)據(jù)集的研發(fā)工作。到目前為止,最大的GFS集群有上千臺機器、上千塊磁盤,并提供了上百TB的存儲能力。

在本文中,我們介紹了為支持分布式應(yīng)用程序而設(shè)計的文件系統(tǒng)接口的擴展,還從多方面討論了我們的設(shè)計,并給出了小批量的benchmark與在現(xiàn)實場景中的使用表現(xiàn)。

1. 引言

為了滿足Google快速增長的數(shù)據(jù)處理需求,我們設(shè)計并實現(xiàn)了GFS。GFS與過去的分布式系統(tǒng)有著很多相同的目標,如性能(performance)、可伸縮性(scalability)、可靠性(reliability)和可用性(availability)。但是我們的設(shè)計來自于我們對我們的應(yīng)用負載與技術(shù)環(huán)境的觀察。這些觀察反映了與過去的分布式系統(tǒng)所做的假設(shè)明顯不同的結(jié)果。因此,我們重新審視的傳統(tǒng)的選擇并探索了完全不同的設(shè)計。

第一,我們認為設(shè)備故常經(jīng)常發(fā)生。GFS由成百上千臺由廉價設(shè)備組成的存儲節(jié)點組成,并被與其數(shù)量相當(dāng)?shù)目蛻舳嗽L問。設(shè)備的數(shù)量和質(zhì)量決定了幾乎在任何時間都會有部分設(shè)備無法正常工作,甚至部分設(shè)備無法從當(dāng)前故障中分恢復(fù)。我們遇到過的問題包括:應(yīng)用程序bug、操作系統(tǒng)bug、人為錯誤和硬盤、內(nèi)存、插頭、網(wǎng)絡(luò)、電源等設(shè)備故障。因此,系統(tǒng)必須具有持續(xù)監(jiān)控、錯誤檢測、容錯與自動恢復(fù)的能力。

第二,文件比傳統(tǒng)標準更大。數(shù)GB大小的文件是十分常見的。每個文件一般包含很多引用程序使用的對象,如Web文檔等。因為我們的數(shù)據(jù)集由數(shù)十億個總計數(shù)TB的對象組成,且這個數(shù)字還在快速增長,所以管理數(shù)十億個幾KG大小的文件是非常不明智的,即使操作系統(tǒng)支持這種操作。因此,我們需要重新考慮像I/O操作和chunk大小等設(shè)計和參數(shù)。

第三,大部分文件會以“追加”(append)的方式變更(mutate),而非“覆寫”(overwrite)。在實際場景中,幾乎不存在對文件的隨機寫入。文件一旦被寫入,即為只讀的,且通常僅被順序讀取。很多數(shù)據(jù)都有這樣的特征。如數(shù)據(jù)分析程序掃描的大型數(shù)據(jù)集、流式程序持續(xù)生成的數(shù)據(jù)、歸檔數(shù)據(jù)、由一臺機器生產(chǎn)并同時或稍后在另一臺機器上處理的數(shù)據(jù)等。鑒于這種對大文件的訪問模式,追加成了為了性能優(yōu)化和原子性保證的重點關(guān)注目標,而客戶端中對chunk數(shù)據(jù)的緩存則不再重要。

第四,同時設(shè)計應(yīng)用程序和文件系統(tǒng)API便于提高整個系統(tǒng)的靈活性。例如,我們放寬了GFS的一致性協(xié)議,從而大幅簡化了系統(tǒng),減少了應(yīng)用程序的負擔(dān)。我們還引入了一種在不需要額外同步操作的條件下允許多個客戶端并發(fā)將數(shù)據(jù)追加到同一個文件的原子性操作。我們將在后文中討論更多的細節(jié)。

目前,我們部署了多個GFS集群并用于不同的目的。其中最大的集群有超過1000個存儲節(jié)點、超過300TB的磁盤存儲,并被數(shù)百臺客戶端連續(xù)不斷地訪問。

2. 設(shè)計概述

2.1 假設(shè)

在設(shè)計能夠滿足我們需求的文件系統(tǒng)時,我們提出并遵循了一些挑戰(zhàn)與機遇并存的假設(shè)。之前我們已經(jīng)提到了一些,現(xiàn)在我們將更詳細地闡述我們的假設(shè)。

  • 系統(tǒng)有許多可能經(jīng)常發(fā)生故障的廉價的商用設(shè)備組成。它必須具有持續(xù)監(jiān)控自身并檢測故障、容錯、及時從設(shè)備故障中恢復(fù)的能力。

  • 系統(tǒng)存儲一定數(shù)量的大文件。我們的期望是能夠存儲幾百萬個大小為100MB左右或更大的文件。系統(tǒng)中經(jīng)常有幾GB的文件,且這些文件需要被高效管理。系統(tǒng)同樣必須支持小文件,但是不需要對其進行優(yōu)化。

  • 系統(tǒng)負載主要來自兩種讀操作:大規(guī)模的流式讀取和小規(guī)模的隨機讀取。在大規(guī)模的流式讀取中,每次讀取通常會讀幾百KB、1MB或更多。來自同一個客戶端的連續(xù)的讀操作通常會連續(xù)讀文件的一個區(qū)域。小規(guī)模的隨機讀取通常會在文件的某個任意偏移位置讀幾KB。性能敏感的應(yīng)用程序通常會將排序并批量進行小規(guī)模的隨機讀取,這樣可以順序遍歷文件而不是來回遍歷。

  • 系統(tǒng)負載還來自很多對文件的大規(guī)模追加寫入。一般來說,寫入的規(guī)模與讀取的規(guī)模相似。文件一旦被寫入就幾乎不會被再次修改。系統(tǒng)同樣支持小規(guī)模隨機寫入,但并不需要高效執(zhí)行。

  • 系統(tǒng)必須良好地定義并實現(xiàn)多個客戶端并發(fā)向同一個文件追加數(shù)據(jù)的語義。我們的文件通常在生產(chǎn)者-消費者隊列中或多路歸并中使用。來自不同機器的數(shù)百個生產(chǎn)者會并發(fā)地向同一個文件追加寫入數(shù)據(jù)。因此,最小化原子性需要的同步開銷是非常重要的。文件在被生產(chǎn)后可能同時或稍后被消費者讀取。

  • 持續(xù)的高吞吐比低延遲更重要。我們的大多數(shù)應(yīng)用程序更重視告訴處理大量數(shù)據(jù),而很少有應(yīng)用程序?qū)蝹€讀寫操作有嚴格的響應(yīng)時間的需求。

2.2 接口

盡管GFS沒有實現(xiàn)像POSIX那樣的標準API,但還是提供了大家較為熟悉的文件接口。文件被路徑名唯一標識,并在目錄中被分層組織。GFS支持如創(chuàng)建(create)、刪除(delete)、打開(open)、關(guān)閉(close)、讀(read)、寫(write)文件等常用操作。

此外,GFS還支持快照(snapshot)和追加記錄(record append)操作。快照操作會以最小代價創(chuàng)建一個文件或一個目錄樹的拷貝。追加記錄操作允許多個客戶端在保證每個獨立的客戶端追加操作原子性的同時能夠并發(fā)地向同一個文件追加數(shù)據(jù)。這對實現(xiàn)如多路歸并、生產(chǎn)者-消費者隊列等多個客戶端不需要額外的鎖即可同時向同一文件追加數(shù)據(jù)非常有益。我們發(fā)現(xiàn)這類文件對于構(gòu)建大型分布式應(yīng)用程序有極高的價值。快照和追加記錄的操作將分別在章節(jié)3.4和章節(jié)3.3討論。

2.3 架構(gòu)

圖1所示,一個GFS集群包括單個master(主服務(wù)器)和多個chunkserver(塊服務(wù)器),并被多個client(客戶端)訪問。每個節(jié)點通常為一個運行著用戶級服務(wù)進程的Linux主機。如果資源允許且可以接受不穩(wěn)定的應(yīng)用程序代碼所帶來的低可靠性,那么可以輕松地在一臺機器上同時運行chunkserver和client。

?圖1 GFS架構(gòu)圖

文件被劃分為若干個固定大小的chunk(塊)。每個chunk被一個不可變的全局唯一的64位chunk handle(塊標識符)唯一標識,chunk handle在chunk被創(chuàng)建時由主節(jié)點分配。chunkserver將chunk作為Linux文件存儲到本地磁盤中,通過chunk handle和byte range(字節(jié)范圍)來確定需要被讀寫的chunk和chunk中的數(shù)據(jù)。為了可靠性考慮,每個chunk會在多個chunkserver中有副本。我們默認存儲三份副本,用戶也可以為不同的命名空間的域指定不同的副本級別。

master維護系統(tǒng)所有的元數(shù)據(jù)。元數(shù)據(jù)包括命名空間(namespace)、訪問控制(access control)信息、文件到chunk的映射和chunk當(dāng)前的位置。master還控制系統(tǒng)級活動如chunk租約(chunk lease)管理、孤兒chunk垃圾回收(garbage collection of orphaned chunks)和chunkserver間的chunk遷移(migration)。master周期性地通過心跳(HeartBeat)消息與每個chunkserver通信,向其下達指令并采集其狀態(tài)信息。

被鏈接到應(yīng)用程序中的GFS client的代碼實現(xiàn)了文件系統(tǒng)API并與master和chunkserver通信,代表應(yīng)用程序來讀寫數(shù)據(jù)。進行元數(shù)據(jù)操作時,client與master交互。而所有的數(shù)據(jù)(譯注:這里指存儲的數(shù)據(jù),不包括元數(shù)據(jù))交互直接由client與chunkserver間進行。因為GFS不提供POXIS API,因此不會陷入到Linux vnode層。

無論client還是chunkserver都不需要緩存文件數(shù)據(jù)。在client中,因為大部分應(yīng)用程序需要流式地處理大文件或者數(shù)據(jù)集過大以至于無法緩存,所以緩存幾乎無用武之地。不使用緩存就消除了緩存一致性問題,簡化了client和整個系統(tǒng)。(當(dāng)然,client需要緩存元數(shù)據(jù)。)chunkserver中的chunk被作為本地文件存儲,Linux系統(tǒng)已經(jīng)在內(nèi)存中對經(jīng)常訪問的數(shù)據(jù)在緩沖區(qū)緩存,因此也不需要額外地緩存文件數(shù)據(jù)。

2.4 單master

采用單master節(jié)點大大簡化了我們的設(shè)計,且讓master可以通過全局的信息做復(fù)雜的chunk分配(chunk placement)和副本相關(guān)的決策。然而,我們必須最小化master節(jié)點在讀寫中的參與,以避免其成為系統(tǒng)瓶頸。client不會直接從master讀取文件數(shù)據(jù),而是詢問master它需要與哪個chunkserver通信。client會在一定時間內(nèi)緩存信息,并直接與對應(yīng)的chunkserver通信以完成后續(xù)操作。

讓我們結(jié)合圖1來解釋一個簡單地“讀”操作。首先,通過固定的chunk大小,client將應(yīng)用程序指定的文件名和chunk偏移量翻譯為該文件中的chunk index(塊序號)。然后,client想master發(fā)送一個包含了文件名和chunk index的請求。master會返回其相應(yīng)的chunk handle和副本所在的位置。client將這個信息以文件名和chunk index為鍵進行緩存。

client接著向最有可能為最近的副本所在的chunkserver發(fā)送請求。請求中指定了chunk handle和byte range。之后,client再次讀取相同的chunk時不再需要與master交互,直到緩存過期或文件被重新打開。事實上,client通常會在同一個請求中請求多個chunk,master也可以返回包含多個chunk的響應(yīng)。這種方式避免了client與master進一步的通信,在幾乎不需要額外開銷的情況下得到更多的信息。

2.5 chunk大小

chunk大小是關(guān)鍵的設(shè)計參數(shù)之一。我們選擇了64MB,其遠大于通常的文件系統(tǒng)的塊大小。每個chunk的副本被作為普通的Linux文件存儲在chunkserver上,其僅在需要時擴展。懶式空間分配(lazy space allocation)避免了內(nèi)部碎片(internal fragmentation)帶來的空間浪費,而內(nèi)部碎片可能是選擇較大的chunk大小所帶來的最大的不利因素。

選擇較大的chunk大小提供了很多重要的優(yōu)勢。第一,減少了client與master交互的次數(shù),因為對一個chunk的讀寫僅需要與master通信一次以請求其位置信息。因為我們的應(yīng)用程序通常連續(xù)地讀寫大文件,所以減少了client與master交互的次數(shù)是尤為重要的。即使對于小規(guī)模的隨機讀取的情況,client也可以輕松地緩存一個數(shù)TB的數(shù)據(jù)集所有的chunk位置信息。第二,因為chunk較大,client更有可能在一個chunk上執(zhí)行更多的操作,這可以通過與chunkserver保持更長時間的TCP連接來減少網(wǎng)絡(luò)開銷。第三,減少了master中保存的元數(shù)據(jù)大小。我們可以將元數(shù)據(jù)保存在master的內(nèi)存中,這樣做提供了更多的優(yōu)勢,這些優(yōu)勢將在章節(jié)2.6.1中討論。

然而,即使有懶式空間分配,較大的chunk大小也存在著缺點。管理僅有幾個chunk的小文件就是其中之一。如果多個client訪問同一個文件,那么存儲這這些文件的chunkserver會成為hot spot(熱點)。在實際情況相愛,因為應(yīng)用程序大部分都順序地讀取包含很多chunk的大文件,所以hot spot不是主要問題。

然而在GFS首次被批處理隊列(batch-queue)系統(tǒng)使用時,確實出現(xiàn)了hot spot問題:一個可執(zhí)行文件被以單個chunk文件的形式寫入了GFS,然后在數(shù)百臺機器上啟動。存儲這個可執(zhí)行程序的幾臺chunkserver因幾百個并發(fā)的請求超載。我們通過提高這種可執(zhí)行文件的副本數(shù)(replication factor)并讓批處理隊列系統(tǒng)錯開應(yīng)用程序啟動時間的方式修復(fù)了這個問題。一個潛在的長期解決方案是在讓client在這種場景下從其他client讀取數(shù)據(jù)。

2.6 元數(shù)據(jù)

master主要存儲三種元數(shù)據(jù):文件和chunk的命名空間(namespace)、文件到chunk的映射和chunk的每個副本的位置。所有元數(shù)據(jù)被存儲在master的內(nèi)存中。前兩種類型(文件和快的命名空間、文件到chunk的映射)還通過將變更(mutation)記錄到一個操作日志(operation log)的方式持久化存儲在master的磁盤上,并在遠程機器上備份。通過日志,我們可以簡單、可靠地更新master的狀態(tài),即使master故障也沒有數(shù)據(jù)不一致的風(fēng)險。master不會持久化存儲chunk的位置信息,而是在啟動時和當(dāng)chunkserver加入集群時向chunkserver詢問其存儲的chunk信息。

2.6.1 內(nèi)存數(shù)據(jù)結(jié)構(gòu)

因為元數(shù)據(jù)被存儲在內(nèi)存中,master可以快速地對其進行操作。此外,在內(nèi)存中存儲元數(shù)據(jù)可以使master周期性掃描整個的狀態(tài)變得簡單高效。這種周期性的掃描被用作實現(xiàn)垃圾回收、chunkserver故障時重做副本、chunkserver間為了負載均衡和磁盤空間平衡的chunk遷移。章節(jié)4.3和章節(jié)4.4會進一步討論這些活動。

這種僅使用內(nèi)存的方法的一個潛在問題是chunk的數(shù)量及整個系統(tǒng)的容量受master的內(nèi)存大小限制。在實際情況中,這并不會成為一個嚴重的限制。master為每個64MB的chunk維護少于64字節(jié)的元數(shù)據(jù)。因為大多數(shù)文件包含多個chunk,所以大部分chunk是滿的,僅最后一個chunk被部分填充。并且因為采用了前綴壓縮的方式緊湊地存儲文件名,每個文件的命名空間數(shù)據(jù)通常需要少于64字節(jié)。

即使當(dāng)有必要支持更大型的文件系統(tǒng)時,增加額外的內(nèi)存的成本,遠遠低于通過內(nèi)存存儲元數(shù)據(jù)所帶來的簡單性、可靠性、性能和靈活性。

2.6.2 chunk位置

master不會持久化保存哪臺chunkserver含有給定的chunk的副本的記錄,而是簡單地在啟動時從chunkserver獲取信息。隨后,master就可以保證自己的記錄是最新的,因為master控制著所有chunk的分配并通過周期性的心跳消息監(jiān)控chunkserver狀態(tài)。

最初我們試圖讓master持久化保存chunk位置信息,但是后來我們意識到在chunkserver啟動時和啟動后周期性請求數(shù)據(jù)要簡單的多。這樣做消除了當(dāng)chunkserver加入或離開集群、更改名稱、故障、重啟等問題時,保持master和chunkserver同步的問題。在有著數(shù)百臺服務(wù)器的集群中,這些事件都會經(jīng)常發(fā)生。

另一種理解這種設(shè)計的方法是,chunkserver對其磁盤上有或沒有哪些chunk有著最終決定權(quán)。因為chunkserver中的錯誤會導(dǎo)致chunk消失(例如磁盤可能損壞或被禁用)或一個操作者可能重命名一個chunkserver。因此,試圖在master上維護一個持久化的快位置信息視圖是沒有以意義的。

2.6.3 操作日志

操作日志包含重要的元數(shù)據(jù)變更的歷史記錄。這是GFS的核心。它不僅是元數(shù)據(jù)中唯一被持久化的記錄,還充當(dāng)了定義并發(fā)操作順序的邏輯時間線。帶有版本號的文件和chunk都在他們被創(chuàng)建時由邏輯時間唯一、永久地確定。

操作日志是GFS至關(guān)重要的部分,其必須被可靠存儲,且在元數(shù)據(jù)的變更被持久化前不能讓client對變更可見。否則當(dāng)故障發(fā)生時,即使chunk本身沒有故障,但是整個文件系統(tǒng)或者client最近的操作會損壞。我們將操作日志備份到多臺遠程主機上,且只有當(dāng)當(dāng)前操作記錄條目被本地和遠程主機均寫入到了磁盤后才能向客戶端發(fā)出響應(yīng)。master會在操作記錄被寫入前批量合并一些操作記錄來減少寫入和備份操作對整個系統(tǒng)吞吐量的影響。

master通過重放(replay)操作日志來恢復(fù)其文件系統(tǒng)的狀態(tài)。操作日志要盡可能小以減少啟動時間。當(dāng)日志超過一定大小時,master會對其狀態(tài)創(chuàng)建一個檢查點(checkpoint),這樣master就可以從磁盤加載最后一個檢查點并重放該檢查點后的日志來恢復(fù)狀態(tài)。檢查點的結(jié)構(gòu)為一個緊湊的B樹(B-tree)這樣它就可以在內(nèi)存中被直接映射,且在查找命名空間時不需要進行額外的解析。這進一步提高了恢復(fù)速度,并增強了系統(tǒng)的可用性。

因為創(chuàng)建一個檢查點需要一段時間,所以master被設(shè)計為可以在不推遲新到來的變更的情況下創(chuàng)建檢查點。創(chuàng)建檢查點時,master會切換到一個新的日志文件并在一個獨立的線程中創(chuàng)建檢查點。這個新的檢查點包含了在切換前的所有變更。一個有著幾百萬個文件的集群可以再一分鐘左右創(chuàng)建一個檢查點。當(dāng)檢查點被創(chuàng)建完成后,它會被寫入master本地和遠程主機的磁盤中。

恢復(fù)僅需要最后一個完整的檢查點和后續(xù)的日志文件。舊的檢查點和日志文件可以隨意刪除,不過我們會不保留一段時間以容災(zāi)。創(chuàng)建檢查點時發(fā)生錯誤不會影響日志的正確性,因為恢復(fù)代碼會檢測并跳過不完整的檢查點。

2.7 一致性模型

GFS寬松的一致性模型可以很好地支持我們的高度分布式應(yīng)用程序,且實現(xiàn)起來簡單高效。我們將討論GFS提供的保證和其對應(yīng)用程序的意義。我們也會重點討論GFS如何維持這些保證,但會將細節(jié)留給本論文的其他部分。

2.7.1 GFS提供的保證

文件命名空間的變更(例如創(chuàng)建文件)操作時原子性的。它們僅由master處理。命名空間鎖保證了原子性和正確性(章節(jié)4.1);master的操作日志定義了這些操作的全局總順序(章節(jié)2.6.3)。

在數(shù)據(jù)變更后,無論變更的成功與否,一個文件區(qū)域(file region)的狀態(tài)都取決于變更類型。表1總結(jié)了變更后文件區(qū)域的狀態(tài)。如果一個文件區(qū)域的任意一個副本被任何client讀取總能得到相同的數(shù)據(jù),那么這個文件區(qū)域狀態(tài)為consistent(一致的)。在一個文件區(qū)域的數(shù)據(jù)變更后,如果它是一致的,且client總能看到其寫入的內(nèi)容(譯注:并發(fā)寫等操作后文件區(qū)域雖然consistent,但是client不一定能夠讀到其寫入的數(shù)據(jù),后文會描述這種情況。),那么這個文件區(qū)域的狀態(tài)為defined(確定的)(defined狀態(tài)包含了consistent狀態(tài))。文件區(qū)域在并發(fā)變更執(zhí)行后的狀態(tài)為consistent but undefined(一致的但非確定的):所有客戶端能考到同樣的數(shù)據(jù),但數(shù)據(jù)可能并不反映任何一個變更寫入的數(shù)據(jù)。通常,數(shù)據(jù)融合了多個變更的內(nèi)容。文件區(qū)域在一個失敗的變更后狀態(tài)會變?yōu)閕nconsistent(不一致的)(且undefined):不同client在不同時刻可能看到不同的數(shù)據(jù)。下面我摩恩將描述我們的應(yīng)用程序如何區(qū)分defined和undefined的區(qū)域。應(yīng)用程序不需要進一步區(qū)分不同種的undefined狀態(tài)。

表1 變更后文件區(qū)域狀態(tài)
Table 1: File Region State After MutationWrite(寫入)Record Append(記錄追加)
串行成功
(Secrial success)
defined
(確定的)
defined interspersed with inconsistent
確定的,但部分不一致
并發(fā)成功
(Secrial success)
consistent but undefined
(一致的但非確定的)
失敗(Failure)inconsistent
(不一致的)

數(shù)據(jù)變更操作可能為write或record append(譯注:record append操作與文件的append有所不同,下文中會有對record append的介紹)。write操作會在應(yīng)用程序指定的文件與偏移處寫入數(shù)據(jù)。record append會將數(shù)據(jù)至少一次(at least once)地原子性地寫入文件,即使在record append的同時可能存在并發(fā)的變更,但是record append寫入位置是由GFS選擇的偏移量(章節(jié)3.3)。(與常規(guī)的append不同,append僅會在client認為的文件末尾處寫入數(shù)據(jù)。)record append的偏移量會被返回到client,這個偏移量為record append寫入的數(shù)據(jù)的起始位置。除此之外,GFS可能會在記錄的中間插入填充(padding)和或重復(fù)的記錄。它們占用的區(qū)域狀態(tài)為inconsistent的,通常情況下,它們的數(shù)量遠少于用戶數(shù)據(jù)。

在一系列變更執(zhí)行成功后,被變更的文件區(qū)域狀態(tài)為defined的,且該區(qū)域中包含最后一次變更寫入的數(shù)據(jù)。這一點是GFS通過以下方式實現(xiàn)的:(a)對chunk執(zhí)行變更時,其所有副本按照相同的順序應(yīng)用變更(章節(jié)3.1)(b)使用chunk版本號(chunk version)來檢測因chunkserver宕機而錯過了變更的陳舊的chunk副本(章節(jié)4.5)。陳舊的chunk副本永遠不會在執(zhí)行變更時被使用,也不會在master返回client請求的chunk的位置時被使用。它們會盡早地被作為垃圾回收。

由于client會緩存chunk的位置,在緩存信息刷新前,client可能會訪問陳舊的副本。這個時間窗口會受緩存過期時間和下一次打開文件限制(下一次打開文件會清除文件的所有chunk位置信息)。除此之外,由于我們大多數(shù)文件是僅追加的,陳舊的副本的通常會返回一個版本較早的結(jié)束位置處的數(shù)據(jù),而不是陳舊的數(shù)據(jù)(譯注:這里陳舊的數(shù)據(jù)指錯過了write變更的數(shù)據(jù))。當(dāng)reader重試并與master通信時,它將立刻獲取目前的chunk位置。

即使在變更被成功應(yīng)用的很長時間后,設(shè)備故障仍然可以損壞(corrupt)會銷毀(destroy)數(shù)據(jù)。GFS通過master和所有chunkserver周期性握手的方式來確定故障的chunkserver,并通過校驗和(checksunmming)的方式檢測數(shù)據(jù)損壞(章節(jié)5.2)。一旦出現(xiàn)問題,數(shù)據(jù)會盡快地從一個合法的副本恢復(fù)章節(jié)4.3)。一個chunk只有在GFS作出反應(yīng)前(通常在幾分鐘內(nèi))失去了所有的副本,chunk才會不可逆地丟失。即使在這種情況下,chunk也僅變得不可用而非損壞,因為應(yīng)用程序可以收到明確的錯誤而非損壞的數(shù)據(jù)。(譯注:本節(jié)中的“損壞corrupt”指讀到錯誤的數(shù)據(jù),“銷毀(destory)”指數(shù)據(jù)丟失。)

2.7.2 對應(yīng)用程序的影響

GFS應(yīng)用程序可以通過一些簡單的技術(shù)來使用其寬松的一致性模型,且這些技術(shù)已經(jīng)因其他目標而被使用,如:依賴append而不是overwrite、檢查點、自驗證寫入(writing self-validating)、自標識記錄(self-identifying records)。

在實際使用中,我們所有的應(yīng)用程序都通過append而不是overwrite的方式對文件進行變更。其中一個典型的引用場景是:一個write從頭到尾地生成一個文件。它會周期性地為已經(jīng)寫入的文件數(shù)據(jù)創(chuàng)建檢查點,并在所有數(shù)據(jù)都被寫入文件后自動將其重命名為一個永久的文件名。檢查點可能包含應(yīng)用程序級別的校驗和。reader會驗證文件僅處理跟上最新的檢查點的文件區(qū)域,這些區(qū)域的狀態(tài)一定的“defined”的。盡管這種方法有一致性和并發(fā)問題,它仍很好地滿足了我們的需求。append的效率遠高于隨機寫入,且在應(yīng)用程序故障時更容易恢復(fù)。檢查點機制允許writer在重啟時增量寫入,并能夠防止reader處理那些雖然已經(jīng)被成功寫入文件但是從應(yīng)用程序的角度看仍然不完整的文件數(shù)據(jù)。

另一種典型的用途是,許多write并發(fā)地向同一個文件append數(shù)據(jù)以獲得合并后的結(jié)果或文件作為生產(chǎn)者-消費者隊列使用。record append的“至少一次追加(append-at-least-once)”語義保證了每個write的輸出。而reader偶爾需要處理填充和重復(fù)的數(shù)據(jù),如下文所述。每條被writer準備好的記錄包含如校驗和的額外信息,這樣,記錄的合法性就可被校驗。一個reader通過校驗和來識別并丟棄額外的填充和記錄。如果rearder無法容忍偶爾發(fā)生的重復(fù)(如果重復(fù)的記錄可能觸發(fā)非冪等(non-idempotent)運算),它可以使用記錄中的唯一標識符來對齊進行過濾。通常,在命名應(yīng)用程序相關(guān)的實體時(如web文檔),總會使用唯一的標識符。數(shù)據(jù)記錄的I/O的充能都在庫代碼中(除了去重),可以被我們的應(yīng)用程序使用,且其還適應(yīng)于Google實現(xiàn)的其他文件接口。通過這些庫,帶有極少的重復(fù)的記錄,總會被以相同順序交付給reader。

3. 系統(tǒng)交互

在我們設(shè)計系統(tǒng)時,我們讓master盡可能少地參與所有操作。在此背景下,我們將描述client、master和chunkserver如何交互來實現(xiàn)數(shù)據(jù)變更、原子地record append和快照操作。

3.1 租約和變更順序

改變chunk或元數(shù)據(jù)的操作被稱為“變更”,如write或append。chunk變更時,其每個副本都會應(yīng)用變更。我們使用租約(lease)來維護副本間變更順序的一致性。master向其中一份副本授權(quán)一個變更的租約,我們稱這個副本為primary(譯注:有時也可代指primary副本所在的chunkserver)。primary為應(yīng)用于該chunk的所有變更選取順序。所有副本都會按照這個順序來應(yīng)用變更。因此,全局的變更順序首先由master選取的租約授權(quán)順序定義,接著在租約內(nèi)由primary選取的順序編號定義。

這種租約機制是為了最小化master管理負載而設(shè)計的。租約的初始超時時間為60秒。然而,一旦chunk被變更,primary就可以向master請求延長租約時間,或者(通常為)接受來自master的租約時間延長操作。這些租約延長請求和租約授權(quán)請求依賴master與chunkserver間周期性地心跳消息來實現(xiàn)。有時master可能會在租約過期前視圖撤銷租約(例如,當(dāng)master想禁止對正在被重命名的文件進行變更時)。即使master與一個primary的通信丟失,master仍可以在舊租約過期后安全地向另一個副本授權(quán)新的租約。

圖2中,我們將通過帶編號的控制流來講解一次write的流程。

圖2 寫操作的控制與數(shù)據(jù)流

  • client向master詢問哪個chunkserver持有指定chunk的租約及該chunk的其他副本的位置。如果沒有chunkserver持有租約,那么master會選擇一個副本對其授權(quán)(這一步在圖中沒有展示)。

  • master回復(fù)primary副本的標識符和其他副本(也稱secondary)的位置。client為后續(xù)的變更緩存這些信息。client只有當(dāng)primary不可訪問或primary向client回復(fù)其不再持有租約時才需要再次與master通信。

  • client將數(shù)據(jù)推送到所有副本。client可以按任意順序推送。每個chunkserver都會將數(shù)據(jù)在內(nèi)部的LRU中緩存,直到數(shù)據(jù)被使用或緩存老化失效(age out)。通過將數(shù)據(jù)流和控制流解耦,我們可以使用基于網(wǎng)絡(luò)拓撲的技術(shù)來提高開銷高昂的數(shù)據(jù)流的性能,且與哪臺chunkserver是primary無關(guān)。章節(jié)3.2將對此進一步討論。

  • 一旦所有副本都確認收到了數(shù)據(jù),client會向primary發(fā)送一個write請求。這個請求標識了之前推送到所有副本的數(shù)據(jù)的作用。primary會為其收到的所有的變更(可能來自多個client)分配連續(xù)的編號,這一步提供了重要的順序。primary對在本地按照該順序應(yīng)用變更。

  • primary將write請求繼續(xù)傳遞給其他secondary副本。每個secondary副本都按照primary分配的順序來應(yīng)用變更。

  • 所有的secondary副本通知primary其完成了變更操作。

  • primary回復(fù)client。任意副本遇到的任何錯誤都會被報告給client。即使錯誤發(fā)生,write操作可能已經(jīng)在primary或secondary的任意子集中被成功執(zhí)行。(如果錯誤在primary中發(fā)生,那么操作將不會被分配順序,也不會被繼續(xù)下發(fā)到其他副本。)只要錯誤發(fā)生,該請求都會被認為是失敗的,且被修改的區(qū)域的狀態(tài)為inconsistent。client中的代碼會通過重試失敗的變更來處理這種錯誤。首先它會重試幾次步驟(3)到步驟(7),如果還沒有成功,再從write請求的初始操作開始重試。

  • 如果應(yīng)用程序發(fā)出的一次write請求過大或跨多個chunk,GFS的client代碼會將其拆分成多個write操作。拆分后的write請求都按照上文中的控制流執(zhí)行,但是可能存在與其他client的并發(fā)的請求交叉或被其他client的并發(fā)請求覆蓋的情況。因此,共享的文件區(qū)域最終可能包含來自不同client的片段。但共享的文件區(qū)域中的內(nèi)容最終是相同的,因為每個操作在所有副本上都會以相同的順序被成功執(zhí)行。正如章節(jié)2.7中所述,這會使文件區(qū)域變?yōu)閏onsistent but undefined狀態(tài)。

    3.2 數(shù)據(jù)流

    為了高效地利用網(wǎng)絡(luò),我們對數(shù)據(jù)流與控制流進行了解耦。在控制流從client向primary再向所有secondary推送的同時,數(shù)據(jù)流沿著一條精心挑選的chunkserver鏈以流水線的方式線性推送。我們的目標是充分利用每臺機器的網(wǎng)絡(luò)帶寬,避免網(wǎng)絡(luò)瓶頸和高延遲的鏈路,并最小化推送完所有數(shù)據(jù)的時延。

    為了充分利用機器的網(wǎng)絡(luò)帶寬,數(shù)據(jù)會沿著chunkserver鏈線性地推送,而不是通過其他拓撲結(jié)構(gòu)(如樹等)分配發(fā)送。因此,每臺機器全部的出口帶寬都被用來盡可能快地傳輸數(shù)據(jù),而不是非給多個接受者。

    為了盡可能地避免網(wǎng)絡(luò)瓶頸和高延遲的數(shù)據(jù)鏈路(例如,交換機間鏈路(inter-switch)經(jīng)常同時成為網(wǎng)絡(luò)瓶頸和高延遲鏈路),每臺機器會將數(shù)據(jù)傳遞給在網(wǎng)絡(luò)拓撲中最近的的且還沒有收到數(shù)據(jù)的機器。假設(shè)client正準備將數(shù)據(jù)推送給S1~S4。client會將數(shù)據(jù)發(fā)送給最近的chunkserver,比如S1。S1會將數(shù)據(jù)傳遞給S2~S4中離它最近的chunkserver,比如S2。同樣,S2會將數(shù)據(jù)傳遞給S3~S4中離它最近的chunkserver,以此類推。由于我們的網(wǎng)絡(luò)拓撲非常簡單,所以可以通過IP地址來準確地估算出網(wǎng)絡(luò)拓撲中的“距離”。

    最后,我們通過流水線的方式通過TCP連接傳輸數(shù)據(jù),以最小化時延。當(dāng)chunkserver收到一部分數(shù)據(jù)時,它會立刻開始將數(shù)據(jù)傳遞給其他chunkserver。因為我們使用全雙工的交換網(wǎng)絡(luò),所以流水線可以大幅減少時延。發(fā)送數(shù)據(jù)不會減少接受數(shù)據(jù)的速度。如果沒有網(wǎng)絡(luò)擁塞,理論上將BBB個字節(jié)傳輸給RRR個副本所需的時間為B/T+RLB/T+RLB/T+RL,其中TTT是網(wǎng)絡(luò)的吞吐量,LLL是兩臺機器間的傳輸時延。通常,我們的網(wǎng)絡(luò)連接吐吞量TTT為100Mbps100Mbps100Mbps,傳輸時延LLL遠小于1ms1ms1ms。

    3.3 原子性record append

    GFS提供了一種叫做record append的原子性append操作。在傳統(tǒng)的write操作中,client會指定數(shù)據(jù)寫入的偏移量。對同一個文件區(qū)域的并發(fā)write操作不是串行的,可能會導(dǎo)致該區(qū)域中不同段的數(shù)據(jù)來自多個cllient。然而在record append中,client僅需指定待追加的數(shù)據(jù)。GFS會為其選擇一個偏移量,在該偏移量處至少一次地原子性地將數(shù)據(jù)作為一個連續(xù)的字節(jié)序列追加到文件,并將該偏移量返回給client。這很像Unix系統(tǒng)中,在不存在多writer并發(fā)寫入帶來的競態(tài)條件下,寫入以O(shè)_APPEND模式打開的文件的情況。

    record append被大量應(yīng)用在我們的有多個來自不同機器的client向同一個文件并發(fā)append數(shù)據(jù)的分布式應(yīng)用程序中。如果通過傳統(tǒng)的write操作,那么client還需要額外的復(fù)雜且開銷很高的同步操作(例如分布式鎖管理)。這種文件在我們的工作環(huán)境下常被作為MPSC(multiple-producer/single-consumer,多生產(chǎn)者單消費者)隊列使用,或是作為包含了來自多個client的數(shù)據(jù)合并后的結(jié)果被使用。

    record append是變更的一種,也遵循章節(jié)3.1中的控制流,僅在primary端稍有點額外的邏輯。在client將數(shù)據(jù)推送到所有副本的最后一個chunk之后,client會向primary發(fā)送一個請求。primary會檢查當(dāng)新記錄追加到該chunk之后,是否會導(dǎo)致該chunk超過最大的chunk大小限制(64MB)。如果會超出chunk大小限制,primary會將該chunk填充到最大的大小,并通知secondary也做相同的操作,再回復(fù)客戶端,使其在下一個chunk上重試該操作。record append操作限制了每次最多寫入最大chunk大小的四分之一的數(shù)據(jù),以保證在最壞的情況下產(chǎn)生的碎片在可接受的范圍內(nèi)。(譯注:過大的請求會被拆分成多個請求,如章節(jié)3.1中所述。)在一般情況下,記錄大小都在最大限制以內(nèi),這樣primary會向數(shù)據(jù)追加到它的副本中,并通知secondary在與其追加的偏移量相同的位置處寫入數(shù)據(jù),并將最終成功操作的結(jié)果返回給client。

    如果record append操作在任何一個副本中失敗,那么client會重試操作。這樣會導(dǎo)致同一個chunk的不同副本中可能包含不同的數(shù)據(jù),這些數(shù)據(jù)可能是同一條記錄的部分或完整的副本。GFS不保證所有副本在字節(jié)級別一致,其只保證record append的數(shù)據(jù)作為一個單元被原子性地至少寫入一次。這一點很容易證明,因為數(shù)據(jù)必須在某個chunk的所有副本的相同偏移位置處寫入。此外,在record append之后,每個副本都至少與最后一條記錄一樣長。這樣,任何未來的新記錄都會被分配到一個更高的偏移位置或者一個新chunk,即使另一個副本成為了primary也能保證這個性質(zhì)。這樣,被record append操作成功寫入的區(qū)域在一致性方面都將是defined狀態(tài)(因此也是consistent的),而這些defined區(qū)域間的文件區(qū)域是inconsistent的(因此也是undefined的)。我們應(yīng)用程序會通過章節(jié)2.7.2中討論的方式處理inconsistent的區(qū)域。

    3.4 快照

    快照操作幾乎會在瞬間對一個文件或一個目錄樹(被稱為源)完成拷貝,同時能夠盡可能少地打斷正在執(zhí)行的變更。我們的用戶使用快照操作來快速地對一個龐大的數(shù)據(jù)集的一個分支進行拷貝(或?qū)ζ淇截愒龠M行拷貝等等),或者在實驗前對當(dāng)前狀態(tài)創(chuàng)建檢查點,這樣就可以在試驗后輕松地提交或回滾變更。

    我們使用類似AFS[5]的標準的寫入時復(fù)制技術(shù)來實現(xiàn)快照。當(dāng)master收到快照請求的時候,它首先會撤銷快照涉及到的文件的chunk上所有未完成的租約。這確保了對這些chunk在后續(xù)的寫入時都需要與master交互以查找租約的持有者。這會給master優(yōu)先拷貝這些chunk的機會。

    在租約被收回或過期后,master會將快照操作記錄到日志中,并寫入到磁盤。隨后,master會通過在內(nèi)存中創(chuàng)建一個源文件或源目錄樹的元數(shù)據(jù)的副本的方式來進行快照操作。新創(chuàng)建的快照文件與源文件指向相同的chunk。

    在快照操作后,首次想要對chunkCCC進行write操作的client會向master發(fā)送一個請求以找到當(dāng)前的租約持有者。master會檢測到chunkCCC的引用數(shù)超過1個。master會推遲對client的響應(yīng),并選取一個新的chunk handler C′C'C′。接著,master請求每個當(dāng)前持有chunkCCC副本的chunkserver去創(chuàng)建一個新chunkC′C'C′。通過在與源chunk相同的chunkserver上創(chuàng)建新chunk,可以保證數(shù)據(jù)只在本地拷貝,而不會通過網(wǎng)絡(luò)拷貝(我們的磁盤大概比100Mb100Mb100Mb的以太網(wǎng)連接快3倍左右)。在這之后,請求的處理邏輯就與處理任何其他chunk的請求一樣了:master向新chunkC′C'C′的一個副本授權(quán)租約并將其響應(yīng)client的請求。這樣,client就可以像平常一樣對chunk進行write操作,且client并不知道這個chunk是剛剛從一個已有的chunk創(chuàng)建來的。

    4. master操作

    master執(zhí)行所有命名空間操作。除此之外,master還管理整個系統(tǒng)中chunk的副本:master做chunk分配(placement)決策、創(chuàng)建新chunk與副本、協(xié)調(diào)各種系統(tǒng)范圍的活動以保持chunk副本數(shù)飽和、平衡所有chunkserver的負載并回收未使用的存儲。現(xiàn)在我們將討論這些主題。

    4.1 命名空間管理與鎖

    master的很多操作可能消耗很長時間,例如:快照操作必須收回其涉及到的chunk所在的chunkserver的租約。當(dāng)這些操作執(zhí)行時,我們不希望推遲master的其他操作。因此,我們允許同時存在多個運行中的操作,并對命名空間的區(qū)域使用鎖機制來保證操作正確地串行執(zhí)行。

    不像很多傳統(tǒng)的文件系統(tǒng),GFS沒有用來記錄目錄中有哪些文件的數(shù)據(jù)結(jié)構(gòu)。GFS也不支持對同一個文件或目錄起別名(alias)(如Unix系統(tǒng)中的硬鏈接(hard link)或軟鏈接(symbolic link))。GFS在邏輯上用一個完整路徑名到元數(shù)據(jù)的查找表來表示命名空間。通過前綴壓縮技術(shù),這個查找表可在內(nèi)存中高效地表示。在命名空間樹上的每個節(jié)點(既可能是一個文件的絕對路徑名,也可能是一個目錄的絕對路徑名)都有一個與之關(guān)聯(lián)的讀寫鎖(read-write lock)。

    master的每個操作執(zhí)行前都會請求一系列的鎖。通常,如果master的操作包含命名空間/d1/d2/…/dn/leaf/d1/d2/…/dn/leaf/d1/d2/…/dn/leaf,master會在目錄/d1/d1/d1、/d1/d2/d1/d2/d1/d2,…,/d1/d2/…/dn/d1/d2/…/dn/d1/d2/…/dn上請求讀取鎖,并在完整路徑名/d1/d2/…/dn/leaf/d1/d2/…/dn/leaf/d1/d2/…/dn/leaf上請求讀取鎖或?qū)懭腈i。其中,leafleafleaf可能是文件或者目錄,這取決于執(zhí)行的操作。

    現(xiàn)在,我們將說明鎖機制如何在/home/user/home/user/home/user正在被快照到/save/user/save/user/save/user時,防止/home/user/foo/home/user/foo/home/user/foo被創(chuàng)建。快照操作會在/home/home/home和/save/save/save上請求讀取鎖、在/home/user/home/user/home/user和/save/user/save/user/save/user上請求寫入鎖。文件創(chuàng)建操作需要在/home/home/home進和/home/user/home/user/home/user上請求讀取鎖,在/home/user/foo/home/user/foo/home/user/foo上請求寫入鎖。由于它們試圖在/home/user/home/user/home/user上獲取鎖時發(fā)生沖突,因此這兩個操作可以正確地串行執(zhí)行。因為GFS中沒有目錄數(shù)據(jù)結(jié)果或像inode一樣的數(shù)據(jù)結(jié)構(gòu),所以無需在修改時對其進行保護,因此在文件創(chuàng)建操作時不需要獲取其父目錄的寫入鎖。其父目錄上的讀取鎖已經(jīng)足夠保護其父目錄不會被刪除。

    這種鎖機制提供了一個非常好的性質(zhì):允許在同一目錄下并發(fā)地執(zhí)行變更。例如,在同一目錄下的多個文件創(chuàng)建操作可以并發(fā)執(zhí)行:每個文件創(chuàng)建操作都獲取其父目錄的讀取鎖與被創(chuàng)建的文件的寫入鎖。目錄名上的讀取鎖足夠防止其被刪除、重命名或快照。文件名上的寫入鎖可以防止相同同名文件被創(chuàng)建兩次。

    因為命名空間可能含有很多的結(jié)點,所以讀寫鎖對象會在使用時被懶式創(chuàng)建,并一旦其不再被使用就會被刪除。此外,為了防止死鎖,鎖的獲取順序總是一致的:首先按照命名空間樹中的層級排序,在同一層級內(nèi)按照字典順序排序。

    4.2 副本分配

    GFS集群在多個層級上都高度分布。GFS通常有數(shù)百個跨多個機架的chunkserver。這些chunkserver可能會被來自相同或不同機架上的數(shù)百個clienet訪問。在不同機架上的兩臺機器的通信可能會跨一個或多個交換機。另外,一個機架的出入帶寬可能小于這個機架上所有機器的出入帶寬之和。多層級的分布為數(shù)據(jù)的可伸縮性、可靠性和可用性帶來了特有的挑戰(zhàn)。

    chunk副本分配策略有兩個目標:最大化數(shù)據(jù)可靠性和可用性、最大化網(wǎng)絡(luò)帶寬的利用。對于這兩個目標,僅將副本分散在所有機器上是不夠的,這樣做只保證了容忍磁盤或機器故障且只充分利用了每臺機器的網(wǎng)絡(luò)帶寬。我們必須在機架間分散chunk的副本。這樣可以保證在一整個機架都被損壞或離線時(例如,由交換機、電源電路等共享資源問題引起的故障),chunk的一些副本仍存在并保持可用狀態(tài)。除此之外,這樣還使對chunk的流量(特別是讀流量)能夠充分利用多個機架的總帶寬。而另一方面,寫流量必須流經(jīng)多個機架,這是我們資源做出的權(quán)衡。

    4.3 chunk創(chuàng)建、重做副本、重均衡

    chunk副本的創(chuàng)建可能由三個原因引起:chunk創(chuàng)建、重做副本(re-replication)和重均衡(rebalance)。

    當(dāng)master創(chuàng)建一個chunk的時候,它會選擇初始化空副本的位置。位置的選擇會參考很多因素:(1)我們希望在磁盤利用率低于平均值的chunkserver上放置副本。隨著時間推移,這樣將平衡chunkserver間的磁盤利用率(2)我們希望限制每臺chunkserver上最近創(chuàng)建的chunk的數(shù)量。盡管創(chuàng)建chunk本身開銷很小,但是由于chunk時寫入時創(chuàng)建的,且在我們的一次追加多次讀取(append-once-read-many)的負載下chunk在寫入完成后經(jīng)常是只讀的,所以master還要會可靠的預(yù)測即將到來的大量的寫入流量。(3)對于以上討論的因素,我們希望將chunk的副本跨機架分散。

    當(dāng)chunk可用的副本數(shù)少于用戶設(shè)定的目標值時,master會重做副本副本。chunk副本數(shù)減少可能有很多種原因,比如:chunkserver可能變得不可用、chunkserver報告其副本被損壞、chunkserver的磁盤因為錯誤變得不可用、或者目標副本數(shù)增加。每個需要重做副本的chunk會參考一些因素按照優(yōu)先級排序。這些因素之一是當(dāng)前chunk副本數(shù)與目標副本數(shù)之差。例如,我們給失去兩個副本的chunk比僅失去一個副本的chunk更高的優(yōu)先級。另外,我們更傾向于優(yōu)先為還存在的文件的chunk重做副本,而不是優(yōu)先為最近被刪除的文件(見章節(jié)4.4)重做。最后,為了最小化故障對正在運行的應(yīng)用程序的影響,我們提高了所有正在阻塞client進程的chunk的優(yōu)先級。

    master選取優(yōu)先級最高的chunk,并通過命令若干chunkserver直接從一個存在且合法的副本拷貝的方式來克隆這個chunk。新副本位置的選取與創(chuàng)建新chunk時位置選取的目標類似:均衡磁盤空間利用率、限制在單個chunkserver上活動的克隆操作數(shù)、在機架間分散副本。為了防止克隆操作的流量遠高于client流量的情況發(fā)生,master需要對整個集群中活動的克隆操作數(shù)和每個chunkserver上活動的克隆操作數(shù)進行限制。除此之外,在克隆操作中,每個chunkserver還會限制對源chunkserver的讀請求,以限制每個克隆操作占用的總帶寬。

    最后,每隔一段時間master會對副本進行重均衡:master會檢測當(dāng)前的副本分布并移動副本位置,使磁盤空間和負載更加均衡。同樣,在這個過程中,master會逐漸填充一個新的chunkserver,而不會立刻讓來自新chunk的高負荷的寫入流量壓垮新的chunkserver。新副本放置位置的選擇方法與我們上文中討論過的類似。此外,master必須刪除一個已有副本。通常,master會選擇刪除空閑磁盤空間低于平均的chunkserver上的副本,以均衡磁盤空間的使用。

    4.4 垃圾回收

    在文件被刪除后,GFS不會立刻回收可用的物理存儲空間。master僅在周期性執(zhí)行懶式垃圾回收時回收物理存儲空間,其中垃圾回收分為文件級垃圾回收和chunk級垃圾回收。我們發(fā)現(xiàn)這種方法可以讓系統(tǒng)更為簡單可靠。

    4.4.1 垃圾回收機制

    當(dāng)一個文件被應(yīng)用程序刪除時,master會像執(zhí)行其他操作時一樣立刻將刪除操作寫入日志。但是master不會立刻對資源進行回收,而是將待刪除的文件重命名為一個帶有刪除時間戳的隱藏文件名。當(dāng)master周期性地掃描文件系統(tǒng)命名空間時,它會刪除已經(jīng)存在超過三天(用戶可以配置這個間隔時間)的這種隱藏文件。在文件被徹底刪除之前,仍可通過該文件被重命名后的特殊的新文件名對其進行訪問,也可以通過將其重命名為正常文件的方式撤銷刪除。當(dāng)隱藏文件被從命名空間中移除時,其在內(nèi)存中的元數(shù)據(jù)也會被刪除。這種方式可以有效地切斷文件和其對應(yīng)的chunk的鏈接。

    和上文介紹的文件級垃圾回收類似,在進行chunk級垃圾回收時,master會周期性掃描chunk命名空間,并找出孤兒chunk(orphaned chunk)(例如哪些無法被任何文件訪問到的chunk)并刪除這些chunk的元數(shù)據(jù)。在chunkserver周期性地與master進行心跳消息交換時,chunkserver會報告其擁有的chunk的子集,而master會回復(fù)這些chunk中元數(shù)據(jù)已經(jīng)不存在的chunk的標識。chunkserver可以自由地刪除這些元數(shù)據(jù)已經(jīng)不存在的chunk的副本。

    4.4.2 關(guān)于垃圾回收的討論

    分布式系統(tǒng)垃圾回收通常是一個很困難的問題,其往往需要在編程時使用復(fù)雜的解決方案。但是在我們的場景下它非常簡單。因為文件到chunk的映射由master專門管理,所以我們可以輕松地識別所有chunk的引用。同樣,因為chunk的副本在每個chunkserver上都是Linux系統(tǒng)中指定目錄下的文件,所以我們也可以輕松地識別所有chunk的副本。所有master中沒有記錄的副本都會被視為垃圾。

    這種暫存待回收文件的垃圾回收方法相比餓漢式回收有很多優(yōu)勢。第一,這種方法在設(shè)備經(jīng)常出現(xiàn)故障的大規(guī)模可伸縮分布式系統(tǒng)中非常簡單可靠。chunk的創(chuàng)建可能僅在部分chunkserver上成功而在其他chunkserver上失敗,這樣會導(dǎo)致系統(tǒng)中出現(xiàn)master不知道的副本。且副本刪除消息可能會丟失,這樣master在其自身和chunkserver故障時都必須重新發(fā)送該消息。垃圾回收機制為清理那些不知道是否有用的副本提供了一個統(tǒng)一且可靠的方法。第二,垃圾回收機制將對存儲空間的回收操作合并為master的后臺活動,如周期性掃描命名空間和周期性地與chunkserver握手。因此,垃圾回收機制可以分批回收存儲空間并平攤回收的開銷。另外,垃圾回收僅在master相對空閑時執(zhí)行。這樣,master可以更迅速的相應(yīng)需要及時響應(yīng)的來自client的請求。第三,延遲回收存儲空間可以防止意外的不可逆刪除操作。

    根據(jù)我們的實際經(jīng)驗,延遲回收的主要缺點是:當(dāng)用戶存儲空間緊張時,延遲回收會讓用戶難以釋放存儲空間。快速創(chuàng)建并刪除臨時文件的應(yīng)用程序可能無法立刻重用存儲空間。為了解決這個問題,我們在用戶再次顯示刪除已刪除文件時,加快了對存儲空間的回收。同時,我們允許用戶對不同的命名空間應(yīng)用不同的副本與回收策略。例如,用戶可以指定某個目錄樹下的所有文件都不需要副本,且當(dāng)這個目錄樹下的文件被刪除時立刻且無法撤銷地將其從文件系統(tǒng)中移除。

    4.5 陳舊副本檢測

    如果chunkserver因故障離線時錯過了對其中的chunk的變更,那么該chunkserver中chunk的副本會變?yōu)殛惻f的副本。master會為每一個chunk維護一個chunk版本號(chunk version number),用來區(qū)分最新的和陳舊的副本。

    master每當(dāng)為一個chunk授權(quán)新租約時,都會增加chunk的版本號并同時其最新的副本。master和這些副本都持久化保存這個新版本號。這一步發(fā)生在master響應(yīng)任何client前,即在chunk可以被寫入前。如果一個副本當(dāng)前不可用,那么這個副本的chunk版本號不會增長。這樣,當(dāng)這個chunkserver重啟時并向master報告其包含的chunk和chunk對應(yīng)的版本號時,master會檢測出這個chunkserver中的副本是陳舊的。如果master收到了比它的記錄中更高的chunk版本號,master會認為其授權(quán)租約失敗,并將更高的版本號視為最新的版本號。

    master在周期性垃圾回收時會刪除陳舊的副本。即使在master回收陳舊副本之前,當(dāng)client向master請求該副本的chunk時,master仍會認為該陳舊的副本不存在。另一種保護措施是,當(dāng)master通知client哪個chunkserver持有指定chunk的租約時,和當(dāng)master在克隆操作中命令一個chunkserver從另一個chunkserver讀取chunk時,其請求中需要帶有chunk的版本號。client或者chunkserver會在執(zhí)行操作時驗證版本號以確保其始終在操作最新的數(shù)據(jù)。

    5. 錯誤容忍與診斷

    在我們設(shè)計GFS時,最大的挑戰(zhàn)之一就是處理經(jīng)常發(fā)生的設(shè)備故障。設(shè)備的質(zhì)量和數(shù)量讓故障發(fā)生不再是異常事件,而是經(jīng)常發(fā)生的事。我們既無法完全信任機器,也無法完全新人磁盤。設(shè)備故障可能導(dǎo)致系統(tǒng)不可用,甚至?xí)?dǎo)致數(shù)據(jù)損壞。我們將討論我們是如何應(yīng)對這些挑戰(zhàn)的,以及系統(tǒng)內(nèi)建的用來診斷系統(tǒng)中發(fā)生的不可避免的問題的工具。

    5.1 高可用

    在由數(shù)百臺服務(wù)器組成的GFS集群中,在任意時間總會有一些服務(wù)器不可用。我們通過兩個簡單但有效的策略保證整個系統(tǒng)高可用:快速恢復(fù)和副本。

    5.1.1 快速恢復(fù)

    在master和chunkserver的設(shè)計中,它們都會保存各自的狀態(tài),且無論它們以哪種方式終止運行,都可以在數(shù)秒內(nèi)重新啟動。事實上,我們并不區(qū)分正常終止和非正常的終止。通常,服務(wù)會直接被通過殺死進程的方式終止。當(dāng)client和其他服務(wù)器的請求超時時,它們會在發(fā)生一個時間很短的故障,并隨后重新連接到重啟后的服務(wù)器并重試該請求。章節(jié)6.2.2中有啟動時間相關(guān)的報告。

    5.1.2 chunk副本

    正如之前討論的,每個chunk會在不同機架的多個chunkserver上存有副本。用戶可以為不同命名空間的文件制定不同的副本級別。副本級別默認為3。當(dāng)有chunkserver脫機或通過哦校驗和(見章節(jié)5.2)檢測到損壞的副本時,master根據(jù)需求克隆現(xiàn)有的副本以保證每個chunk的副本數(shù)都是飽和的。盡管副本策略可以很好地滿足我們的需求,我們還是探索了其他形式的跨服務(wù)器的冗余策略以滿足我們?nèi)找鎵堥L的只讀數(shù)據(jù)存儲需求,如:奇偶校驗碼(parity code)或擦除碼(erasure code)。因為我們的流量主要來自append和讀操作,而不是小規(guī)模的隨機寫操作,所以我們希望在松散耦合的系統(tǒng)中,既有挑戰(zhàn)性又要可管理地去實現(xiàn)這些復(fù)雜的冗余策略。

    5.1.3 master副本

    為了保證可靠性,master的狀態(tài)同樣有副本。master的操作日志和檢查點被在多臺機器上復(fù)制。只有當(dāng)變更在被日志記錄并被寫入,master本地和所有master副本的磁盤中后,這個變更才被認為是已提交的。為了簡單期間,一個master進程既要負責(zé)處理所有變更又要負責(zé)處理后臺活動,如垃圾回收等從內(nèi)部改變系統(tǒng)的活動。當(dāng)master故障時,其幾乎可以立刻重啟。如果運行master進程的機器故障或其磁盤故障,在GFS之外的負責(zé)監(jiān)控的基礎(chǔ)架構(gòu)會在其它持有master的操作日志副本的機器上啟動一個新的master進程。client僅通過一個規(guī)范的命名來訪問master結(jié)點(例如gfs-test),這個規(guī)范的命名是一個DNS別名,其可以在master重新被分配到另一臺機器時被修改為目標機器。

    此外,“影子”master節(jié)點(“shadow” master)可以提供只讀的文件系統(tǒng)訪問,即使在主master結(jié)點脫機時它們也可以提供服務(wù)。因為這些服務(wù)器可能稍稍滯后于主master服務(wù)器(通常滯后幾分之一秒),所以這些服務(wù)器是影子服務(wù)器而非鏡像服務(wù)器。這些影子master服務(wù)器增強了那些非正在被變更的文件和不介意讀到稍舊數(shù)據(jù)的應(yīng)用程序的可用性。實際上,由于文件內(nèi)容是從chunkserver上讀取的,所以應(yīng)用程序不會讀取到陳舊的文件內(nèi)容。能夠在一個很短的時間窗口內(nèi)被讀取到的陳舊的數(shù)據(jù)只有文件元數(shù)據(jù),如目錄內(nèi)容和訪問控制信息。

    為了讓自己的元數(shù)據(jù)跟隨主master變化,影子master服務(wù)器會持續(xù)讀取不斷增長的操作日志副本,并像主master一樣按照相同的順序?qū)ζ鋽?shù)據(jù)結(jié)構(gòu)應(yīng)用變更。像主master一樣,影子master服務(wù)器也會在啟動時從chunkserver拉取數(shù)據(jù)來獲取chunk副本的位置(啟動后便很少拉取數(shù)據(jù)),并頻繁地與chunkserver交換握手信息來監(jiān)控它們的狀態(tài)。只有因主master決定創(chuàng)建或刪除副本時,影子master服務(wù)器上的副本位置才取決于主master服務(wù)器。

    5.2 數(shù)據(jù)完整性

    每個chunkserver都使用校驗和來檢測存儲的數(shù)據(jù)是否損壞。由于GFS集群通常在數(shù)百臺機器上有數(shù)千chunk磁盤,所以集群中經(jīng)常會出現(xiàn)磁盤故障,從而導(dǎo)致數(shù)據(jù)損壞或丟失(第七章中介紹了一個誘因)。我們可以通過chunk的其他副本來修復(fù)損壞的chunk,但不能通過比較chunkserver間的副本來檢測chunk是否損壞。除此之外,即使內(nèi)容不同的副本中的數(shù)據(jù)也可能都是合法的:GFS中變更的語義(特別是前文中討論過的record append)不會保證副本完全相同。因此,每個chunkserver必須能夠通過維護校驗和的方式獨立的驗證副本中數(shù)據(jù)的完整性。

    一個chunk被劃分為64KB的block。每個block有其對應(yīng)的32位校驗和。就像其他元數(shù)據(jù)一樣,校驗和也在內(nèi)存中保存且會被通過日志的方式持久化存儲。校驗和與用戶數(shù)據(jù)是分開存儲的。

    對于讀取操作,無論請求來自client還是其他chunkserver,chunkserver都會在返回任何數(shù)據(jù)前校驗所有包含待讀取數(shù)據(jù)的block的校驗和。因此,chunkserver不會將損壞的數(shù)據(jù)傳給其他機器。如果一個block中數(shù)據(jù)和記錄中低的校驗和不匹配,那么chunkserver會給請求者返回一個錯誤,并向master報告校驗和不匹配。隨后,請求者會從其他副本讀取數(shù)據(jù),而master會從該chunk的其他副本克隆這個chunk。當(dāng)該chunk新的合法的副本被安置后,master會通知報告了校驗和不匹配的chunkserver刪除那份損壞的副本。

    校驗和對讀取性能的影響很小。因為我們的大部分讀操作至少會讀跨幾個block的內(nèi)容,我們只需要讀取并校驗相對少量的額外數(shù)據(jù)。GFS客戶端代碼通過嘗試將讀取的數(shù)據(jù)與需要校驗的block邊界對其的方式,進一步地減小了校驗開銷。除此之外,chunkserver上校驗和的查找與比較不需要I/O操作,且校驗和計算操作經(jīng)常與其他操作在I/O上重疊,因此幾乎不存在額外的I/O開銷。

    因為向chunk末尾append數(shù)據(jù)的操作在我們的工作負載中占主要地位,所以我們對這種寫入場景的校驗和計算做了大量優(yōu)化。在append操作時,我們僅增量更新上一個block剩余部分的校驗和,并為append的新block計算新校驗和。即使最后一個block已經(jīng)損壞且目前沒被檢測到,增量更新后的該block的新校驗和也不會與block中存儲的數(shù)據(jù)匹配。在下一次讀取該block時,GFS會像往常一樣檢測到數(shù)據(jù)損壞。

    相反,如果write操作覆蓋了一個chunk已存在的范圍,那么我們必須讀取并驗證這個范圍的頭一個和最后一個block,再執(zhí)行write操作,最后計算并記錄新的校驗和。如果我們沒有在寫入前校驗頭一個和最后一個block,新的校驗和可能會掩蓋這兩個block中沒被覆寫的區(qū)域中存在的數(shù)據(jù)損壞問題。

    chunkserver可以在空閑期間掃描并驗證非活動的chunk的內(nèi)容。這樣可以讓我們檢測到很少被讀取的chunk中的數(shù)據(jù)損壞。一旦檢測到數(shù)據(jù)損壞,master可以創(chuàng)建一個新的未損壞的副本并刪除損壞的副本。這樣可以防止master將chunk的非活動的但是已損壞的副本識別成數(shù)據(jù)合法的副本。

    5.3 診斷工具

    全面且詳細的診斷日志以極小的開銷為問題定位、調(diào)試和性能分析提供了很大的幫助。如果沒有日志,理解機器間短暫且不重復(fù)的交互將變得非常困難。GFS服務(wù)器會生成用來記錄重要事件(如chunkserver上線或離線)和所有RPC請求與響應(yīng)的診斷日志。這些診斷日志可以隨意刪除,不會影響到系統(tǒng)正確性。不過,如果磁盤空間允許,我們將盡可能地保持這些日志。

    RPC日志包括通過網(wǎng)絡(luò)收發(fā)的請求和響應(yīng)中除讀寫的文件數(shù)據(jù)之外的詳細內(nèi)容。在診斷問題時,我們可以通過整合不同機器中的日志并將請求與響應(yīng)匹配的方式,重建整個交互歷史。同樣,這些日志也可用來跟蹤壓力測試、性能分析等情況。

    因為日志是順序且異步寫入的,因此日志對性能的影響非常小,并帶來了很大的好處。其中最近的事件也會在內(nèi)存中保存,以便在持續(xù)的在線監(jiān)控中使用。

    6. 性能測試

    在本章中,我們將展示一些小批量的benchmark,以說明在GFS架構(gòu)和實現(xiàn)中的瓶頸。我們還將展示一些Google在真是集群中使用時的一些指標。

    6.1 小批量benchmark

    我們在一個由1個master、2個master副本、16個chunkserver和16個client組成的GFS集群中測量性能表現(xiàn)。該配置的選擇僅為了便于測試。通常一個GFS集群會由數(shù)百個chunkserver和數(shù)百個client組成。

    所有的機器都采用雙核1.4GHz的奔騰III處理器、2GB內(nèi)存、兩塊5400轉(zhuǎn)的80GB磁盤和100Mbpc全雙工以太網(wǎng),并連接到一臺HP2524交換機。其中所有的19臺GFS服務(wù)器都連接到同一臺交換機,所有的16臺client機器都連接到另一臺交換機。這兩個交換機之間通過1Gbps連接。

    3 總吞吐量(上面的曲線表示在網(wǎng)絡(luò)拓撲中的理論極限。下面的曲線表示測量到的吞吐量。測量結(jié)果曲線顯示了95%置信區(qū)間的誤差柱,在一些情況下,由于測量值的方差很低,置信區(qū)間在圖中難以辨認。

    6.1.1 read操作

    NNN個client同時從GFS讀取數(shù)據(jù)。每個client從320GB的數(shù)據(jù)集中隨機選取4MB的區(qū)域讀取。讀操作將重復(fù)256次,即每個client最終將讀取1GB的數(shù)據(jù)。chunkserver總計有32GB內(nèi)存,因此我們預(yù)測讀操作中最多10%命中Linux緩沖區(qū)緩存。我們的測試結(jié)果應(yīng)該接近冷緩存的結(jié)果。

    **圖3(a)**展示了NNN個client的總讀取速率和理論速率上限。整體的理論速率在125MB/s125MB/s125MB/s時達到峰值,此時兩個交換機間的1Gbps1Gbps1Gbps的鏈路達到飽和;或者每個client的理論速率在12.5MB/s12.5MB/s12.5MB/s時達到峰值,此時它的100Mbps100Mbps100Mbps的網(wǎng)絡(luò)接口達到飽和。當(dāng)僅有一臺client在讀取時,我們觀測到其讀取速率為10MB/s10MB/s10MB/s,在每臺client理論上限的80%。當(dāng)16個client一起讀取時,總讀取速率達到了94MB/s94MB/s94MB/s,大致達到了理論上限125MB/s125MB/s125MB/s的75%,平均每個client的讀取速率為6MB/s6MB/s6MB/s。因為reader的數(shù)量增加導(dǎo)致多個reader從同一個chunkserver讀取的概率增加,所以讀取速率從理論值的80%下降到了75%。

    6.1.2 write操作

    NNN個client同時向NNN個不同的文件寫入。每個client通過一系列的1MB1MB1MB的寫操作向一個新文件寫入總計1GB1GB1GB數(shù)據(jù)。**圖3(b)**展示了整體的寫入速率和理論速率上限。因為我們需要將每個字節(jié)寫入16個chunkserver中的三個,每個chunkserver的連接輸入速率為12.5MB/s12.5MB/s12.5MB/s,所以整體的理論寫入速率上限為67MB/s67MB/s67MB/s。

    譯注:67MB/s67MB/s67MB/s的理論寫入速率上限的計算方式為如下。因為集群中總計有16個chunkserver,每個chunkserver的100Mbps100Mbps100Mbps全雙工連接為輸入速率為12.5MB/s12.5MB/s12.5MB/s。數(shù)據(jù)有3份副本。因此,當(dāng)所有chunkserver的連接輸入全部飽和時,寫入的速率為12.5MB/s×16÷3=67MB/s12.5MB/s \times 16 \div 3 = 67MB/s12.5MB/s×16÷3=67MB/s。根據(jù)在章節(jié)3.2中對數(shù)據(jù)流的介紹可知,在數(shù)據(jù)寫入時,client僅與chunkserver中的primary副本間有一次完整的數(shù)據(jù)傳輸,其他secondary副本數(shù)據(jù)均通過chunkserver遞交。因此在本實驗的集群中,每個chunkserver的連接輸入飽和時,兩個交換機建的數(shù)據(jù)傳輸速率為67MB/s67MB/s67MB/s,即數(shù)據(jù)寫入的速率。小于交換機間的最大傳輸速率1Gbps1Gbps1Gbps,因此不會因交換機間的連接產(chǎn)生瓶頸。

    實驗觀測到的每個client的寫入速率為6.3MB/s6.3MB/s6.3MB/s,大概是理論上限的一半。網(wǎng)絡(luò)棧是造成這一現(xiàn)象的罪魁禍首。在我們使用流水線的方式將數(shù)據(jù)推送到chunk副本時,網(wǎng)絡(luò)棧的表現(xiàn)不是很好。數(shù)據(jù)從一個副本傳遞給另一個副本的時延降低了整體的寫入速率。

    16個client的整體寫入速率達到了35MB/s35MB/s35MB/s,大概是理論上限的一半。與讀取相同,當(dāng)client的數(shù)量增加時,更有可能出現(xiàn)多個client并發(fā)地向同一個chunkserver寫入的情況。此外,因為write操作需要向3份不同的副本寫入,所以16個writer比16個reader更有可能出現(xiàn)碰撞的情況。write操作比我們預(yù)想的要慢。但是在實際環(huán)境中,這并不是主要問題。即使它增加了單個client的時延,但是在有大量client的情況下它并沒有顯著影響系統(tǒng)的整體寫入帶寬。

    6.1.3 record append操作

    **圖3(c)**展示了record append操作的性能表現(xiàn)。NNN個client同時向同一個文件append數(shù)據(jù)。其性能受存儲該文件最后一個chunk的chunkserver的網(wǎng)絡(luò)帶寬限制,與client的數(shù)量無關(guān)。當(dāng)僅有1個client時,record append的速率為6.0MB/s6.0MB/s6.0MB/s,當(dāng)client的數(shù)量增加到16個時,速率下降到4.8MB/s4.8MB/s4.8MB/s。網(wǎng)絡(luò)擁塞和不同client的網(wǎng)絡(luò)傳輸速率不同是造成record append速率下降的主要原因。

    在實際環(huán)境中,我們的應(yīng)用程序往往會并發(fā)地向多個這樣的文件追加數(shù)據(jù)。換句話說,即NNN個client同時地向MMM個共享的文件append數(shù)據(jù),其中NNN與MMM均為數(shù)十或數(shù)百。因此,實驗中出現(xiàn)的chunkserver的網(wǎng)絡(luò)擁塞在實際環(huán)境中并不是大問題,因個client可以在chunkserver忙著處理一個文件時向另一個文件寫入數(shù)據(jù)。

    6.2 現(xiàn)實中的集群

    現(xiàn)在我們來考察在Google中使用的兩個集群,它們代表了其他類似的集群。集群A是數(shù)百個工程師常用來研究或開發(fā)的集群。其中典型的任務(wù)由人啟動并運行幾個小時。這些任務(wù)會讀幾MB到幾TB的數(shù)據(jù),對其分析處理,并將結(jié)果寫回到集群中。集群B主要用于生產(chǎn)數(shù)據(jù)的處理。其中的任務(wù)持續(xù)時間更長,會不斷地生成數(shù)TB的數(shù)據(jù)集,且偶爾才會有人工干預(yù)。在這兩種情況中,每個任務(wù)都有許多過程進程組成,這些進程包括許多機器對許多文件同時的讀寫操作。

    6.2.1 存儲

    正如表2所示,兩個集群都有數(shù)百個chunkserver,有數(shù)TB的磁盤存儲空間,且大部分存儲空間都被使用,但還沒滿。其中“已使用空間”包括所有chunk的副本占用的空間。幾乎所有文件都以3份副本存儲。因此,集群分別存儲了18TB18TB18TB和52TB52TB52TB的數(shù)據(jù)。

    這兩個集群中的文件數(shù)相似,但集群B中停用文件(dead file)比例更大。停用文件即為被刪除或被新副本替換后還未被回收其存儲空間的文件。同樣,集群B中chunk數(shù)量更多,因為其中文件一般更大。

    表2 兩個GFS集群的特征集群AB
    Chunkserver數(shù)量342227
    可用磁盤空間
    已使用空間
    72 TB
    55 TB
    180 TB
    155 TB
    文件數(shù)
    停用文件數(shù)
    chunk數(shù)
    735 k
    22 k
    992 k
    737 k
    232 k
    1550 k
    chunkserver元數(shù)據(jù)大小
    master元數(shù)據(jù)大小
    13 GB
    48 MB
    21 GB
    60 MB

    6.2.2 元數(shù)據(jù)

    在chunkserver中,總共存儲了數(shù)十GB的元數(shù)據(jù),其中大部分是用戶數(shù)據(jù)的每64KB大小的block的校驗和。除此之外,chunkserver中的保存元數(shù)據(jù)只有章節(jié)4.5中討論的chunk版本號。大部分的文件元數(shù)據(jù)是文件名,我們對其采用前綴壓縮的形式存儲。其他的文件元數(shù)據(jù)包括文件所有權(quán)和權(quán)限、文件到chunk的映射、每個chunk當(dāng)前的版本號。除此之外,我們還存儲了chunk當(dāng)前的副本位置和chunk的引用計數(shù)(以實現(xiàn)寫入時拷貝等)。

    無論是chunkserver還是master,每個服務(wù)器中僅有50MB到100MB元數(shù)據(jù)。因此,服務(wù)器恢復(fù)的速度很快。服務(wù)器只需要幾秒鐘的時間從磁盤讀取元數(shù)據(jù),隨后就能應(yīng)答查詢請求。然而,master的恢復(fù)稍微有些慢,其通常需要30到60秒才能恢復(fù),因為master需要從所有的chunkserver獲取chunk的位置信息。

    6.2.3 讀寫速率

    表3展示了不同時間段的讀寫速率。兩個集群在測量開始后均運行了大概一周的時間。(集群最近已因升級到新版本的GFS而重啟過。)

    從重啟后,集群的平均寫入速率小于30MB/s30MB/s30MB/s。當(dāng)我們測量時,集群B正在執(zhí)行以大概100MB/s100MB/s100MB/s寫入生成的數(shù)據(jù)的活動,因為需要將數(shù)據(jù)傳遞給三份副本,該活動造成了300MB/s300MB/s300MB/s的網(wǎng)絡(luò)負載。

    讀操作的速率比寫操作的速率要高得多。正如我們假設(shè)的那樣,整體負載主要有讀操作組成而非寫操作。在測量時兩個集群都在執(zhí)行高負荷的讀操作。實際上,集群A已經(jīng)維持580MB/s580MB/s580MB/s的讀操作一周了。集群A的網(wǎng)絡(luò)配置能夠支持750MB/s750MB/s750MB/s的讀操作,所以集群A在高效利用其資源。集群B能夠支持峰值在1300MB/s1300MB/s1300MB/s的讀操作,但集群B的應(yīng)用程序僅使用了380MB/s380MB/s380MB/s。

    表3 兩個GFS集群的性能指標集群AB
    讀速率(過去一分鐘)
    讀速率(過去一小時)
    讀速率(重啟后至今)
    583 MB/s
    562 MB/s
    589 MB/s
    380 MB/s
    384 MB/s
    49 MB/s
    寫速率(過去一分鐘)
    寫速率(過去一小時)
    寫速率(重啟后至今)
    1 MB/s
    2 MB/s
    25 MB/s
    101 MB/s
    117 MB/s
    13 MB/s
    master操作數(shù)(過去一分鐘)
    master操作數(shù)(過去一小時)
    master操作數(shù)(重啟后至今)
    325 Ops/s
    381 Ops/s
    202 Ops/s
    533 Ops/s
    518 Ops/s
    347 Ops/s

    6.2.4 master的負載

    表3中還展示了向master發(fā)送操作指令的速率,該速率大概在美妙200到500次左右。master可以在該速率下輕松地工作,因此這不會成為負載的瓶頸。

    GFS在早期版本中,在某些負載場景下,master偶爾會成為瓶頸。當(dāng)時master會消耗大量的時間來掃描包含成百上千個文件的目錄以尋找指定文件。在那之后,我們修改了master中的數(shù)據(jù)結(jié)構(gòu),允許其通過二分查找的方式高效地搜索命名空間。目前,master已經(jīng)可以輕松地支持每秒上千次的文件訪問。如果有必要,我們還可以通過在命名空間數(shù)據(jù)結(jié)構(gòu)前放置名稱緩存的方式進一步加快速度。

    6.2.5 恢復(fù)時間

    當(dāng)chunkserver故障后,一些chunk的副本數(shù)會變得不飽和,系統(tǒng)必須克隆這些塊的副本以使副本數(shù)重新飽和。恢復(fù)所有chunk需要的時間取決于資源的數(shù)量。在一次實驗中,我們殺掉集群B中的一個chunkserver。該chunkserver上有大概15000個chunk,總計約600GB的數(shù)據(jù)。為了限制重分配副本對正在運行的應(yīng)用程序的影響并提供更靈活的調(diào)度策略,我們的默認參數(shù)限制了集群中只能有91個并發(fā)的克隆操作(該值為集群中chunkserver數(shù)量的40%)。其中,每個克隆操作的速率上限為6.25MB/s6.25MB/s6.25MB/s(50Mbps50Mbps50Mbps)。所有的chunk在23.2分鐘內(nèi)完成恢復(fù),有效地復(fù)制速率為440MB/s440MB/s440MB/s。

    在另一個實驗中,我們殺掉了兩臺均包含16000個chunk和660GB數(shù)據(jù)的chunkserver。這兩個chunkserver的故障導(dǎo)致了266個chunk僅剩一分副本。這266個塊在克隆時有著更高的優(yōu)先級,在2分鐘內(nèi)即恢復(fù)到至少兩份副本的狀態(tài),此時可以保證集群中即使再有一臺chunkserver故障也不會發(fā)生數(shù)據(jù)丟失。

    6.3 負載分解

    在本節(jié)中,我們將詳細介紹兩個GFS集群中的工作負載。這兩個集群與章節(jié)6.2中的類似但并不完全相同。集群X用來研究和開發(fā),集群Y用來處理生產(chǎn)數(shù)據(jù)。

    6.3.1 方法和注意事項

    這些實驗結(jié)果僅包含來自client的請求,因此結(jié)果反映了我們的應(yīng)用程序為整個文件系統(tǒng)帶來的負載情況。結(jié)果中不包括用來處理client請求的內(nèi)部請求和內(nèi)部的后臺活動,如chunkserver間傳遞write數(shù)據(jù)和副本重分配等。

    I/O操作的統(tǒng)計數(shù)據(jù)來源于GFS通過RPC請求日志啟發(fā)式重建得到的信息。例如,GFS的client代碼可能將一個read操作分解為多個RPC請求以提高并行性,通過日志啟發(fā)式重建后,我們可以推斷出原read操作。因為我們的訪問模式是高度一致化的,所以我們期望的錯誤都在數(shù)據(jù)噪聲中。應(yīng)用程序中顯式的日志可能會提供更加準確的數(shù)據(jù),但是重新編譯并重啟上千個正在運行的client是現(xiàn)實的,且從上千臺機器上采集數(shù)據(jù)結(jié)果也非常困難。

    需要注意的一點是,不要過度地推廣我們的負載情況。因為Google對GFS和它的應(yīng)用程序具有絕對的控制權(quán),所以應(yīng)用程序會面向GFS優(yōu)化,而GFS也正是為這些應(yīng)用程序設(shè)計的。雖然這種應(yīng)用程序與文件系統(tǒng)間的互相影響在一般情況下也存在,但是這種影響在我們的例子中可能會更明顯。

    6.3.2 chunkserver的負載

    表4展示了各種大小的操作占比。讀操作的大小呈雙峰分布。64KB以下的小規(guī)模read來自client從大文件查找小片數(shù)據(jù)的seek密集操作。超過512KB的大規(guī)模read來自讀取整個文件的線性讀取。

    在集群Y中,大量的read沒有返回任何數(shù)據(jù)。在我們的應(yīng)用程序中(特別是生產(chǎn)系統(tǒng)中的應(yīng)用程序),經(jīng)常將文件作為生產(chǎn)者-消費者隊列使用。在多個生產(chǎn)者并發(fā)地向同一個文件支架數(shù)據(jù)的同時,會有一個消費者讀末尾的數(shù)據(jù)。偶爾當(dāng)消費者超過生產(chǎn)者時,read即不會返回數(shù)據(jù)。集群X中這種情況出現(xiàn)的較少,因為在集群X中的應(yīng)用程序通常為短期運行的數(shù)據(jù)分析程序,而非長期運行的分布式應(yīng)用程序。

    write也呈同樣的雙峰分布。超過256KB的大規(guī)模write操作通常是由writer中的大量的緩沖區(qū)造成的。小于64KB的小規(guī)模寫操作通常來自于那些緩沖區(qū)小、創(chuàng)建檢查點操作或者同步操作更頻繁、或者是僅生成少量數(shù)據(jù)的writer。

    對于record append操作,集群Y中大規(guī)模的record append操作比集群X中要高很多。因為我們的生產(chǎn)系統(tǒng)使用了集群Y,生產(chǎn)系統(tǒng)的應(yīng)用程序會更激進地面向GFS優(yōu)化。

    表4 各種大小的操作占比(%)
    對于read操作,數(shù)據(jù)大小為實際讀取和傳輸?shù)臄?shù)據(jù)大小,而非請求讀取的總大小。操作類型readwriterecord append
    集群XYXYXY
    0K0.42.60000
    1B...1K0.14.16.64.90.29.2
    1K...8K65.238.50.41.018.915.2
    8K...64K29.945.117.843.078.02.8
    64K...128K0.10.72.31.9< .14.3
    128K...256K0.20.331.60.4< .110.6
    256K...512K0.10.14.27.7< .131.2
    512K...1M3.96.935.528.72.225.5
    1M...inf0.11.81.512.30.72.2

    表5中展示了不同大小的操作中傳輸數(shù)據(jù)的總量的占比。對于所有類型的操作,超過256KB的大規(guī)模操作通常都是字節(jié)傳輸導(dǎo)致的。小于64KB的小規(guī)模read操作通常來自seek操作,這些讀操作傳輸了很小但很重要的數(shù)據(jù)。

    6.3.3 append vs write

    record append操作在我們的系統(tǒng)中被大量使用,尤其是我們的生產(chǎn)系統(tǒng)。在集群X中,write操作和record append操作的操作次數(shù)比例為8:1,字節(jié)傳輸比例為108:1。在集群Y中,這二者的比例分別為2.5:1和3.7:1。這些數(shù)據(jù)顯示了對于兩個集群來說,record append操作的規(guī)模通常比write打。然而。在集群X中,測量期間record append的使用量非常的少。因此。這個測量結(jié)果可能受一兩個有特定緩沖區(qū)大小的應(yīng)用程序影響較大。

    正如我們預(yù)期的那樣,我們的數(shù)據(jù)變更負載主要來自于append而非overwrite。我們測量了primary副本上overwrite的數(shù)據(jù)總量。測量值很接近client故意overwrite數(shù)據(jù)而不append的情況。對于集群X,overwrite的操作總量低于變更操作的0.0003%,字節(jié)數(shù)占比低于總量的0.0001%。對于集群Y,這兩個數(shù)據(jù)均為0.05%。盡管這個比例已經(jīng)很小了,但仍比我們預(yù)期的要高。大部分的overwrite都是由client因錯誤或超時而重試造成的。這本質(zhì)上是由重試機制造成的而非工作負載。

    表5 各種大小的操作字節(jié)傳輸量占比(%)
    對于read操作,數(shù)據(jù)大小為實際讀取和傳輸?shù)臄?shù)據(jù)大小,而非請求讀取的總大小。二者的區(qū)別為,讀取請求可能會試圖讀取超過文件末尾的內(nèi)容。在我們的設(shè)計中,這不是常見的負載。操作類型readwriterecord append
    集群XYXYXY
    1B...1K< .1< .1< .1< .1< .1< .1
    1K...8K13.83.9< .1< .1< .10.1
    8K...64K11.49.32.45.92.30.3
    64K...128K0.30.70.30.322.71.2
    128K...256K0.80.616.50.2< .15.8
    256K...512K1.40.33.47.7< .138.4
    512K...1M65.955.174.158.0.146.8
    1M...inf6.430.13.328.053.97.4

    6.3.4 master的負載

    表6展示了對master的各種類型的請求占比。其中,大部分請求來自read操作詢問chunk位置的請求(FindLocation)和數(shù)據(jù)變更操作詢問租約持有者(FindLeaseLocker)。

    集群X與集群Y中Delete請求量差異很大,因為集群Y存儲被經(jīng)常重新生成或者移動的生產(chǎn)數(shù)據(jù)。一些Delete請求量的差異還隱藏在Open請求中,因為打開并從頭寫入文件時(Unix中以“w”模式打開文件),會隱式地刪除舊版本的文件。

    FindMatchingFiles是用來支持“l(fā)s”或類似文件系統(tǒng)操作的模式匹配請求。不像給master的其他請求,FindMatchingFiles請求可能處理很大一部分命名空間,因此這種請求開銷很高。在集群Y中,這種請求更加頻繁,因為自動化的數(shù)據(jù)處理任務(wù)常通過檢查部分文件系統(tǒng)的方式來了解應(yīng)用程序的全局狀態(tài)。相反,使用集群X的應(yīng)用程序會被用戶更明確地控制,通常會提交知道所需的文件名。

    表6 master請求類型占比(%)集群XY
    Open26.116.3
    Delete0.71.5
    FindLocation64.365.8
    FindLeaseHolder7.813.4
    FindMatchingFiles0.62.2
    All otder combined0.50.8

    7. 開發(fā)經(jīng)歷

    在構(gòu)建和部署GFS的過程中,我們經(jīng)歷了很多問題。其中,有些是操作問題,有些是技術(shù)問題。

    最初,GFS的構(gòu)思是將其作為我們生產(chǎn)系統(tǒng)的后端文件系統(tǒng)。隨著時間推移,GFS的用途演變?yōu)榘搜芯亢烷_發(fā)任務(wù)。GFS開始時幾乎不支持權(quán)限、配額之類的功能,但現(xiàn)在這些功能都變?yōu)镚FS包含的基本功能。雖然生產(chǎn)系統(tǒng)有著良好的紀律并被良好地控制著,但用戶有時卻沒有。因此,其需要更多的基礎(chǔ)設(shè)施來防止用戶互相干擾。

    我們最大的一些問題是磁盤問題和Linux相關(guān)問題。我們的許多磁盤都想Linux驅(qū)動程序聲稱它們支持很多版本的IDE(譯注:本文IDE指集成設(shè)備電路Intergated Drive Electronics)協(xié)議,但事實上,它們可能只能可靠地響應(yīng)最近幾個版本的協(xié)議。因為這些協(xié)議都非常相似,所以大部分時間驅(qū)動器都能正常工作。但協(xié)議版本偶爾不匹配就會導(dǎo)致驅(qū)動器和內(nèi)核中所認為的驅(qū)動器的狀態(tài)不一致。由于內(nèi)核中的問題,數(shù)據(jù)會無法察覺地損壞。這個問題驅(qū)動我們通過校驗和的方式檢測數(shù)據(jù)是否損壞,同時我們修改了內(nèi)核去處理協(xié)議不匹配的問題。

    早些時候,由于*fsync()*的開銷,我們在Linux2.2內(nèi)核中遇到了一些問題。這個函數(shù)的開銷和文件成正比,而不是和修改的部分大小成正比。這對我們使用較大的操作日志造成了問題(特別是在我們實現(xiàn)檢查點機制以前)。我們曾經(jīng)通過同步寫入的方式來解決這個問題,直到遷移到Linux2.4。

    另一個Linux的問題是一個讀寫鎖。當(dāng)任何地址空間的線程從磁盤換入頁(讀鎖)或者通過*mmap()函數(shù)修改地址空間(寫鎖)時,都必須持有這一個讀寫鎖。我們發(fā)現(xiàn)系統(tǒng)在輕負載下的一個瞬間會出現(xiàn)超時問題,所以我們努力地去尋找資源瓶頸和零星的硬件故障。最終,我們發(fā)現(xiàn)在磁盤線程正在換入之前映射的文件時,這個讀寫鎖阻塞了網(wǎng)絡(luò)主線程,導(dǎo)致其無法將新數(shù)據(jù)映射到內(nèi)存。因為我們主要受網(wǎng)絡(luò)接口限制而非受內(nèi)存拷貝帶寬限制,所以我們用pread()替換了mmap()*函數(shù),其代價是多了一次額外的拷貝操作。

    盡管偶爾會有問題發(fā)生,Linux代碼的可用性還是幫助了我們一次又一次地探索和理解系統(tǒng)行為。當(dāng)時機合適時,我們會改進內(nèi)核并將這些改進與開源社區(qū)分享。

    8. 相關(guān)工作

    就像其他大型的分布式文件系統(tǒng)一樣(如AFS[5]),GFS提供了與位置無關(guān)的命名空間,這可以允許數(shù)據(jù)為了負載均衡和容錯地移動,這一操作對client是透明的。但與AFS不同,GFS將文件數(shù)據(jù)通過類似xFS[1]和Swtift[3]的方式分散到了存儲服務(wù)器上,以釋放集群整體性能并提高容錯能力。

    因為磁盤相對廉價且副本的方式比復(fù)雜的RAID[9]的方式簡單很多,所以GFS僅通過副本的方式作為冗余,因此GFS會比xFS或Swift消耗更多的原始存儲空間。與類似AFS、xFS、Frangipani[12]和Intermezzo[6]的文件系統(tǒng)不同,GFS在系文件系統(tǒng)接口下沒有提供任何的緩存。在我們的目標工作負載中,一個應(yīng)用程序幾乎不會重用數(shù)據(jù),因為其或者流式地處理一個大型數(shù)據(jù)集,或者每次僅在大型數(shù)據(jù)及中隨機地seek并讀取很小一部分的數(shù)據(jù)。

    一些分布式文件系統(tǒng)移除了集中式的服務(wù)器,并依賴分布式算法來實現(xiàn)一致性和管理,如Frangipani、xFS、Minnesota’s GFS[11]和GPFS[10]。我們選擇了集中式的方法來簡化設(shè)計、增強可靠性,同時還獲得了靈活性。集中式的master還大大簡化了復(fù)雜的chunk分配操作和重分配副本的策略,因為master已經(jīng)有了大部分相關(guān)信息,且由master來控制如何變化。我們通過保持master的狀態(tài)大小很小并在其他機器上有充足的副本的方式來提高容錯能力。可伸縮性和高可用性(對于read操作來說)目前通過影子master服務(wù)器機制提供。master狀態(tài)的變化會通過追加到預(yù)寫日志的方式進行持久化。因此我們可以通過適配像Harp[7]中的主拷貝模式(primary-copy scheme)的方法,來提供比當(dāng)前的一致性有更強保證的高可用性。

    我們遇到了一個類似Lustre[8]的問題,即為大量client提供整體的性能。然而,我們通過將重點放在我們的應(yīng)用程序的需求而不是構(gòu)架一個兼容POSIX文件系統(tǒng)的方式,大幅簡化了這個問題。除此之外,GFS假設(shè)大量的設(shè)備是不可靠的,因此容錯是我們設(shè)計中的中心問題。

    GFS非常接近NASD架構(gòu)[4]。NASD架構(gòu)基于通過網(wǎng)絡(luò)連接的磁盤驅(qū)動器,而GFS使用一般的商用機器作為chunkserver,就像NASD的原型那樣。與NASD不同是,我們的chunkserver懶式分配固定大小的chunk,而不是可變長的對象。另外,GFS實現(xiàn)了如負載均衡、副本重分配和恢復(fù)等在生產(chǎn)環(huán)境中需要的特性。

    與Minnesota’s GFS或NASD不同,我們不希望改變存儲設(shè)備的模型。我們著重解決由已有的商用設(shè)備組成的復(fù)雜的分布式系統(tǒng)的日常數(shù)據(jù)處理問題。

    對生產(chǎn)者-消費者隊列的原子性record append操作解決了類似于River的分布式隊列問題。River[2]使用了分布在不同機器上的基于內(nèi)存的隊列和謹慎的數(shù)據(jù)流控制,而GFS采用了可以被多個生產(chǎn)者并發(fā)追加的持久化文件。River的模型支持M:N的分布式隊列,但缺少持久化存儲帶來的容錯能力。而GFS僅支持M:1的高效的隊列。多個消費者可一個讀相同的文件,但必須相互協(xié)調(diào)載入的分區(qū)。

    9. 結(jié)論

    Google File System論證了在產(chǎn)品級硬件上支持大規(guī)模數(shù)據(jù)處理負載的必要特性。雖然很多設(shè)計是為我們特殊的場景定制的,但很多設(shè)計可能適用于規(guī)模和預(yù)算相似的數(shù)據(jù)處理任務(wù)。

    我們根據(jù)我們當(dāng)前和預(yù)期的應(yīng)用程序負載和技術(shù)環(huán)境,重新考察了傳統(tǒng)文件系統(tǒng)設(shè)計中的假設(shè)。我們的考察結(jié)果指向了完全不同的設(shè)計。我們視設(shè)備故障為平常事件而非異常事件。我們優(yōu)化了大部分操作為追加(可能是并發(fā)追加)和讀取(通常為順序讀取)的大文件。我們還擴展并放寬了標準文件系統(tǒng)接口來改進整個系統(tǒng)。

    我們的系統(tǒng)通過持續(xù)的監(jiān)控、備份關(guān)鍵數(shù)據(jù)、自動且快速的恢復(fù)來提供容錯能力。chunk副本讓我們能夠容忍chunkserver故障。這些故障的頻率讓我們設(shè)計了一種新的在線修復(fù)機制:周期性地對client不可見的修復(fù)損壞數(shù)據(jù),并盡快補充丟失的副本。另外,我們通過校驗和的方式來檢測磁盤或IDE子系統(tǒng)級別的數(shù)據(jù)損壞,因為GFS系統(tǒng)中磁盤數(shù)量很多,這類問題是非常普遍的。

    我們的設(shè)計為并發(fā)執(zhí)行多種任務(wù)的reader和writer提供了很高的整體吞吐量。為了實現(xiàn)這一點,我們將通過master進行的文件系統(tǒng)控制和通過chunkserver、client的數(shù)據(jù)傳輸分離開來。我們還通過選取較大的chunk大小和chunk租約(將數(shù)據(jù)變更授權(quán)給primary副本)的方式最小化了master對一般操作的參與度。這種方式讓master變得簡單,且中心化的master不會成為系統(tǒng)瓶頸。我們相信,通過改進網(wǎng)絡(luò)棧,會減少當(dāng)前對單個client的寫入吞吐量的限制。

    GFS成功地滿足了我們的存儲需求,并已經(jīng)在Google內(nèi)部作為研究、開發(fā)和生產(chǎn)數(shù)據(jù)處理的存儲平臺使用。GFS是讓我們能夠進一步創(chuàng)新并攻克web規(guī)模問題的重要工具。

    致謝

    感謝以下對本系統(tǒng)或本論文做出了貢獻的人。Brain Bershad(我們的指導(dǎo)者)和給我我們珍貴的評論和建議的匿名評審員。Anurag Acharya、Jeff Dean和David Desjardins為系統(tǒng)的早期設(shè)計做出了貢獻。Fay Chang致力于chunkserver間副本比較的研究。Guy Edjlali致力于存儲配額的研究。Markus Gutschke致力于測試框架與安全性增強的研究。Fay Chang、Urs Hoelzle、Max Ibel、Sharon Perl、Rob Pike和Debby Wallach對本論文早期的草稿做出了評論。我們在Google的許多勇敢的同事,他們信任這個新文件系統(tǒng)并給我們提出了很多很有用的反饋。Yoshka在早期的測試中提供了幫助。

    參考文獻

    [1] Thomas Anderson, Michael Dahlin, Jeanna Neefe, David Patterson, Drew Roselli, and Randolph Wang. Serverless networkfile 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 diskstriping to provide high I/O data rates. Computer Systems, 4(4):405–436, 1991.

    [4] Garth A. Gibson, David F. Nagle, Khalil Amiri, Jeff Butler, Fay W. Chang, Howard Gobioff, Charles Hardin, ErikRiedel, David Rochberg, and Jim Zelenka. A cost-effective, high-bandwidth storage architecture. In Proceedings of the 8th Architectural Support for Programming Languages and Operating Systems, pages 92–103, San Jose, California, October 1998.

    [5] John Howard, Michael Kazar, Sherri Menees, David Nichols, Mahadev Satyanarayanan, Robert Sidebotham, and Michael West. Scale and performance in a distributed file system. ACM Transactions on Computer Systems, 6(1):51–81, February 1988.

    [6] InterMezzo. Inter-mezzo.org - Logiciel Mac en téléchargement gratuit, 2003.

    [7] Barbara Liskov, Sanjay Ghemawat, Robert Gruber, Paul Johnson, Liuba Shrira, and Michael Williams. Replication in the Harp file system. In 13th Symposium on Operating System Principles, pages 226–238, Pacific Grove, CA, October 1991.

    [8] Lustre. http://www.lustreorg, 2003.

    [9] David A. Patterson, Garth A. Gibson, and Randy H. Katz. A case for redundant arrays of inexpensive disks (RAID). In Proceedings of the 1988 ACM SIGMOD International Conference on Management of Data, pages 109–116, Chicago, Illinois, September 1988.

    [10] FrankSchmuckand Roger Haskin. GPFS: A shared-diskfile system for large computing clusters. In Proceedings of the First USENIX Conference on File and Storage Technologies, pages 231–244, Monterey, California, January 2002.

    [11] Steven R. Soltis, Thomas M. Ruwart, and Matthew T. O’Keefe. The Gobal File System. In Proceedings of the Fifth NASA Goddard Space Flight Center Conference on Mass Storage Systems and Technologies, College Park, Maryland, September 1996.

    [12] Chandramohan A. Thekkath, Timothy Mann, and Edward K. Lee. Frangipani: A scalable distributed file system. In Proceedings of the 16th ACM Symposium on Operating System Principles, pages 224–237, Saint-Malo, France, October 1997.

    總結(jié)

    以上是生活随笔為你收集整理的《The Google File System》gfs论文翻译的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。