一区二区久久-一区二区三区www-一区二区三区久久-一区二区三区久久精品-麻豆国产一区二区在线观看-麻豆国产视频

經典論文翻譯導讀之《Google File System》

  英文原文:The Google File System,編譯:ImportNew - 儲曉穎   新浪微博:@瘋狂編碼中的xiaoY

  【譯者預讀】

  GFS這三個字母無需過多修飾,《Google File System》的論文也早有譯版。但是這不妨礙我們加點批注、重溫經典,并結合上篇Haystack的文章,將GFS、TFS、Haystack進行一次全方位的對比,一窺各巨頭的架構師們是如何權衡利弊、各取所需。

  1. 介紹

  我們設計和實現了GFS來滿足Google與日俱增的數據處理需求。與傳統的分布式文件系統一樣,GFS著眼在幾個重要的目標,比如性能、可伸縮性、可靠性和可用性。不過它也會優先考慮我們自身應用場景的特征和技術環境,所以與早先一些文件系統的設計思想還是有諸多不同。我們取傳統方案之精華、根據自身需求做了大膽的設計創新。在我們的場景中:

  首先,組件故障是常態而不是異常。文件系統包含成百上千的存儲機器,而且是廉價的普通機器,被大量的客戶端機器訪問。這樣的機器質量和數量導致任何時間點都可能有一些機器不可用,甚至無法從當前故障中恢復。導致故障的原因很多,比如應用bug、操作系統bug、人為錯誤,以及磁盤、內存、連接器、網絡等硬件故障,甚至是電力供應。因此,持續監控、錯誤偵測、故障容忍和自動恢復必須全面覆蓋整個系統。

  其次,用傳統視角來看,我們要處理的文件很多都是巨型的,好幾GB的文件也很常見。通常情況下每個文件中包含了多個應用對象,比如web文檔。面對快速增長、TB級別、包含數十億對象的數據集合,如果按數十億個KB級別的小文件來管理,即使文件系統能支持,也是非常不明智的。因此,一些設計上的假設和參數,比如I/O操作和塊大小,需要被重新審視。

  第三,大部分文件發生變化是通過append新數據,而不是覆蓋、重寫已有的數據,隨機寫幾乎不存在。被寫入時,文件變成只讀,而且通常只能是順序讀。很多數據場景都符合這些特征。比如文件組成大型的庫,使用數據分析程序對其掃描。比如由運行中的程序持續生成的數據流。比如歸檔數據。還可能是分布式計算的中間結果,在一臺機器上產生、然后在另一臺處理。這些數據場景都是由制造者持續增量的產生新數據,再由消費者讀取處理。在這種模式下append是性能優化和保證原子性的焦點。然而在客戶端緩存數據塊沒有太大意義。

  第四,向應用提供類似文件系統API,增加了我們的靈活性。松弛的一致性模型設計也極大的簡化了API,不會給應用程序強加繁重負擔。我們將介紹一個原子的append操作,多客戶端能并發的對一個文件執行append,不需考慮任何同步。

  當前我們部署了多個GFS集群,服務不同的應用。最大的擁有超過1000個存儲節點,提供超過300TB的磁盤存儲,被成百上千個客戶端機器大量訪問。

  2 設計概覽

  2.1 假設

  設計GFS過程中我們做了很多的設計假設,它們既意味著挑戰,也帶來了機遇?,F在我們詳細描述下這些假設。

  • 系統是構建在很多廉價的、普通的組件上,組件會經常發生故障。它必須不間斷監控自己、偵測錯誤,能夠容錯和快速恢復。
  • 系統存儲了適當數量的大型文件,我們預期幾百萬個,每個通常是100MB或者更大,即使是GB級別的文件也需要高效管理。也支持小文件,但是不需要著重優化。
  • 系統主要面對兩種讀操作:大型流式讀和小型隨機讀。在大型流式讀中,單個操作會讀取幾百KB,也可以達到1MB或更多。相同客戶端發起的連續操作通常是在一個文件讀取一個連續的范圍。小型隨機讀通常在特定的偏移位置上讀取幾KB。重視性能的應用程序通常會將它們的小型讀批量打包、組織排序,能顯著的提升性能。
  • 也會面對大型的、連續的寫,將數據append到文件。append數據的大小與一次讀操作差不多。一旦寫入,幾乎不會被修改。不過在文件特定位置的小型寫也是支持的,但沒有著重優化。
  • 系統必須保證多客戶端對相同文件并發append的高效和原子性。我們的文件通常用于制造者消費者隊列或者多路合并。幾百個機器運行的制造者,將并發的append到一個文件。用最小的同步代價實現原子性是關鍵所在。文件被append時也可能出現并發的讀。
  • 持久穩定的帶寬比低延遲更重要。我們更注重能夠持續的、大批量的、高速度的處理海量數據,對某一次讀寫操作的回復時間要求沒那么嚴格。

  2.2 接口

  GFS提供了一個非常親切的文件系統接口,盡管它沒有全量實現標準的POSIX API。像在本地磁盤中一樣,GFS按層級目錄來組織文件,一個文件路徑(path)能作為一個文件的唯一ID。我們支持常規文件操作,比如create、delete、open、close、read和write。

  除了常規操作,GFS還提供快照和record append操作??煺湛梢杂煤艿偷幕ㄙM為一個文件或者整個目錄樹創建一個副本。record append允許多個客戶端并發的append數據到同一個文件,而且保證它們的原子性。這對于實現多路合并、制造消費者隊列非常有用,大量的客戶端能同時的append,也不用要考慮鎖等同步問題。這些特性對于構建大型分布式應用是無價之寶。快照和record append將在章節3.4、3.3討論。

  2.3 架構

  一個GFS集群包含單個master和多個chunkserver,被多個客戶端訪問,如圖1所示。圖1中各組件都是某臺普通Linux機器上運行在用戶級別的一個進程。在同一臺機器上一起運行chunkserver和客戶端也很容易,只要機器資源允許。

  文件被劃分為固定大小的chunk。每個chunk在創建時會被分配一個chunk句柄,chunk句柄是一個不變的、全局唯一的64位的ID。chunkserver在本地磁盤上將chunk存儲為Linux文件,按照chunk句柄和字節范圍來讀寫chunk數據。為了可靠性,每個chunk被復制到多個chunkserver上,默認是3份,用戶能為不同命名空間的文件配置不同的復制級別。

  master維護所有的文件系統元數據。包括命名空間,訪問控制信息,從文件到chunk的映射,和chunk位置。它也負責主導一些影響整個系統的活動,比如chunk租賃管理、孤兒chunk的垃圾回收,以及chunkserver之間的chunk遷移。master會周期性的與每臺chunkserver通訊,使用心跳消息,以發號施令或者收集chunkserver狀態。

  每個應用程序會引用GFS的客戶端API,此API與正規文件系統API相似,并且負責與master和chunkserver通訊,基于應用的行為來讀寫數據。客戶端只在獲取元數據時與master交互,真實的數據操作會直接發至chunkserver。我們不需提供嚴格完整的POSIX API,因此不需要hook到Linux的vnode層面。

  客戶端和chunkserver都不會緩存文件數據。客戶端緩存文件數據收益很小,因為大部分應用通常會順序掃描大型文件,緩存重用率不高,要么就是工作集合太大緩存很困難。沒有緩存簡化了客戶端和整個系統,排除緩存一致性問題。(但是客戶端會緩存元數據。)chunkserver不需要緩存文件數據因為chunk被存儲為本地文件,Linux提供的OS層面的buffer緩存已經保存了頻繁訪問的文件。

  2.4 單一Master

  單一master大大的簡化了我們的設計,單一master能夠放心使用全局策略執行復雜的chunk布置、制定復制決策等。然而,我們必須在讀寫過程中盡量減少對它的依賴,它才不會成為一個瓶頸??蛻舳藦牟煌ㄟ^master讀寫文件,它只會詢問master自己應該訪問哪個chunkserver。客戶端會緩存這個信息一段時間,隨后的很多操作即可以復用此緩存,與chunkserver直接交互。

  我們利用圖1來展示一個簡單讀操作的交互過程。首先,使用固定的chunk size,客戶端將應用程序指定的文件名和字節偏移量翻譯為一個GFS文件及內部chunk序號,隨后將它們作為參數,發送請求到master。master找到對應的chunk句柄和副本位置,回復給客戶端??蛻舳司彺孢@些信息,使用GFS文件名+chunk序號作為key。

  客戶端然后發送一個讀請求到其中一個副本,很可能是最近的那個。請求中指定了chunk句柄以及在此chunk中讀取的字節范圍。后面對相同chunk的讀不再與master交互,直到客戶端緩存信息過期或者文件被重新打開。事實上,客戶端通常會在一個與master的請求中順帶多索要一些其他chunk的信息,而且master也可能將客戶端索要chunk后面緊跟的其他chunk信息主動回復回去。這些額外的信息避免了未來可能發生的一些client-master交互,幾乎不會導致額外的花費。

  2.5 chunk size

  chunk size是其中一個關鍵的設計參數。我們選擇了64MB,這是比典型的文件系統的塊大多了。每個chunk副本在chunkserver上被存儲為一個普通的Linux文件,只在必要的時候才去擴展。懶惰的空間分配避免了內部碎片導致的空間浪費,chunk size越大,碎片的威脅就越大。

  chunk size較大時可以提供幾種重要的優勢。首先,它減少了客戶端與master的交互,因為對同一個chunk的讀寫僅需要對master執行一次初始請求以獲取chunk位置信息。在我們的應用場景中大部分應用會順序的讀寫大型文件,chunk size較大(chunk數量就較少)能有效的降低與master的交互次數。對于小型的隨機讀,即使整個數據集合達到TB級別,客戶端也能舒服的緩存所有的chunk位置信息(因為chunk size大,chunk數量小)。其次,既然用戶面對的是較大的chunk,它更可能愿意在同一個大chunk上執行很多的操作(而不是操作非常多的小chunk),這樣就可以對同一個chunkserver保持長期的TCP連接以降低網絡負載。第三,它減少了master上元數據的大小,這允許我們放心的在內存緩存元數據,章節2.6.1會討論繼而帶來的各種好處。

  不過chunk size如果很大,即使使用懶惰的空間分配,也有它的缺點。一個小文件包含chunk數量較少,可能只有一個。在chunkserver上這些chunk可能變成熱點,因為很多客戶端會訪問相同的文件(如果chunk size較小,那小文件也會包含很多chunk,資源競爭可以分擔到各個小chunk上,就可以緩解熱點)。不過實際上熱點沒有導致太多問題,因為我們的應用大部分都是連續的讀取很大的文件,包含很多chunk(即使chunk size較大)。

  然而,熱點確實曾經導致過問題,當GFS最初被用在批量隊列系統時:用戶將一個可執行程序寫入GFS,它只占一個chunk,然后幾百臺機器同時啟動,請求此可執行程序。存儲此可執行文件的chunkserver在過多的并發請求下負載較重。我們通過提高它的復制級別解決了這個問題(更多冗余,分擔壓力),并且建議該系統交錯安排啟動時間。一個潛在的長期解決方案是允許客戶端從其他客戶端讀取數據(P2P模式~)。

  2.6 元數據

  master主要存儲三種類型的元數據:文件和chunk的命名空間,從文件到chunk的映射,每個chunk副本的位置。所有的元數據被保存在master的內存中。前兩種也會持久化保存,通過記錄操作日志,存儲在master的本地磁盤并且復制到遠程機器。使用操作日志允許我們更簡單可靠的更新master狀態,不會因為master的當機導致數據不一致。master不會持久化存儲chunk位置,相反,master會在啟動時詢問每個chunkserver以獲取它們各自的chunk位置信息,新chunkserver加入集群時也是如此。

  2.6.1 內存中數據結構

  因為元數據存儲在內存中,master可以很快執行元數據操作。而且可以簡單高效的在后臺周期性掃描整個元數據狀態。周期性的掃描作用很多,有些用于實現chunk垃圾回收,有些用于chunkserver故障導致的重新復制,以及為了均衡各機器負載與磁盤使用率而執行的chunk遷移。章節4.3和4.4將討論其細節。

  這么依賴內存不免讓人有些顧慮,隨著chunk的數量和今后整體容量的增長,整個系統將受限于master有多少內存。不過實際上這不是一個很嚴重的限制。每個64MB的chunk,master為其維護少于64byte的元數據。大部分chunk是填充滿數據的,因為大部分文件包含很多chunk,只有少數可能只填充了部分。同樣的,對于文件命名空間數據,每個文件只能占用少于64byte,文件名稱會使用前綴壓縮緊密的存儲。

  如果整個文件系統真的擴展到非常大的規模,給master添點內存條、換臺好機器scale up一下也是值得的。為了單一master+內存中數據結構所帶來的簡化、可靠性、性能和彈性,咱豁出去了。

  2.6.2 Chunk位置

  master不會持久化的保存哪個chunkserver有哪些chunk副本。它只是在自己啟動時拉取chunkserver上的信息(隨后也會周期性的執行拉?。?。master能保證它自己的信息時刻都是最新的,因為它控制了所有的chunk布置操作,并用常規心跳消息監控chunkserver狀態。

  我們最初嘗試在master持久化保存chunk位置信息,但是后來發現這樣太麻煩,每當chunkserver加入或者離開集群、改變名稱、故障、重啟等等時候就要保持master信息的同步。一般集群都會有幾百臺服務器,這些事件經常發生。

  話說回來,只有chunkserver自己才對它磁盤上存了哪些chunk有最終話語權。沒理由在master上費盡心機的維護一個一致性視圖,chunkserver上發生的一個錯誤就可能導致chunk莫名消失(比如一個磁盤可能失效)或者運維人員可能重命名一個chunkserver等等。

  2.6.3 操作日志

  操作日志是對重要元數據變更的歷史記錄。它是GFS的核心之一。不僅因為它是元數據唯一的持久化記錄,而且它還要承擔一個邏輯上的時間標準,為并發的操作定義順序。各文件、chunk、以及它們的版本(見章節4.5),都會根據它們創建時的邏輯時間被唯一的、永恒的標識。

  既然操作日志這么重要,我們必須可靠的存儲它,而且直至元數據更新被持久化完成(記錄操作日志)之后,才能讓變化對客戶端可見。否則,我們有可能失去整個文件系統或者最近的客戶端操作,即使chunkserver沒有任何問題(元數據丟了或錯了,chunkserver沒問題也變得有問題了)。因此,我們將它復制到多個遠程機器,直到日志記錄被flush到本地磁盤以及遠程機器之后才會回復客戶端。master會捆綁多個日志記錄,一起flush,以減少flush和復制對整個系統吞吐量的沖擊。

  master可以通過重放操作日志來恢復它的元數據狀態。為了最小化master的啟動時間,日志不能太多(多了重放就需要很久)。所以master會在適當的時候執行“存檔”,每當日志增長超過一個特定的大小就會執行存檔。所以它不需要從零開始回放日志,僅需要從本地磁盤裝載最近的存檔,并回放存檔之后發生的有限數量的日志。存檔是一個緊密的類B樹結構,它能直接映射到內存,不用額外的解析。通過這些手段可以加速恢復和改進可用性。

  因為構建一個存檔會消耗點時間,master的內部狀態做了比較精細的結構化設計,創建一個新的存檔不會延緩持續到來的請求。master可以快速切換到一個新的日志文件,在另一個后臺線程中創建存檔。這個新存檔能體現切換之前所有的變異結果。即使一個有幾百萬文件的集群,創建存檔也可以在短時間完成。結束時,它也會寫入本地和遠程的磁盤。

  恢復元數據時,僅僅需要最后完成的存檔和其后產生的日志。老的存檔和日志文件能被自由刪除,不過我們保險起見不會隨意刪除。在存檔期間如果發生故障(存檔文件爛尾了)也不會影響正確性,因為恢復代碼能偵測和跳過未完成的存檔。

  2.7 一致性模型

  GFS松弛的一致性模型能很好的支持我們高度分布式的應用,而且實現起來非常簡單高效。我們現在討論GFS的一致性保證。

  2.7.1 GFS的一致性保證

  文件命名空間變化(比如文件創建)是原子的,只有master能處理此種操作:master中提供了命名空間的鎖機制,保證了原子性的和正確性(章節4.1);master的操作日志為這些操作定義了一個全局統一的順序(章節2.6.3)

  各種數據變異在不斷發生,被它們改變的文件區域處于什么狀態?這取決于變異是否成功了、有沒有并發變異等各種因素。表1列出了所有可能的結果。對于文件區域A,如果所有客戶端從任何副本上讀到的數據都是相同的,那A就是一致的。如果A是一致的,并且客戶端可以看到變異寫入的完整數據,那A就是defined。當一個變異成功了、沒有受到并發寫的干擾,它寫入的區域將會是defined(也是一致的):所有客戶端都能看到這個變異寫入的完整數據。對同個區域的多個并發變異成功寫入,此區域是一致的,但可能是undefined:所有客戶端看到相同的數據,但是它可能不會反應任何一個變異寫的東西,可能是多個變異混雜的碎片。一個失敗的變異導致區域不一致(也是undefined):不同客戶端可能看到不同的數據在不同的時間點。下面描述我們的應用程序如何區分defined區域和undefined區域。

  數據變異可能是寫操作或者record append。寫操作導致數據被寫入一個用戶指定的文件偏移。而record append導致數據(record)被原子的寫入GFS選擇的某個偏移(正常情況下是文件末尾,見章節3.3),GFS選擇的偏移被返回給客戶端,其代表了此record所在的defined區域的起始偏移量。另外,某些異常情況可能會導致GFS在區域之間插入了padding或者重復的record。他們占據的區域可認為是不一致的,不過數據量不大。

  如果一系列變異都成功寫入了,GFS保證發生變異的文件區域是defined的,并完整的包含最后一個變異。GFS通過兩點來實現:(a) chunk的所有副本按相同的順序來實施變異(章節3.1);(b) 使用chunk版本數來偵測任何舊副本,副本變舊可能是因為它發生過故障、錯過了變異(章節4.5)。執行變異過程時將跳過舊的副本,客戶端調用master獲取chunk位置時也不會返回舊副本。GFS會盡早的通過垃圾回收處理掉舊的副本。

  因為客戶端緩存了chunk位置,所以它們可能向舊副本發起讀請求。不過緩存項有超時機制,文件重新打開時也會更新。而且,我們大部分的文件是append-only的,這種情況下舊副本最壞只是無法返回數據(append-only意味著只增不減也不改,版本舊只意味著會丟數據、少數據),而不會返回過期的、錯誤的數據。一旦客戶端與master聯系,它將立刻得到最新的chunk位置(不包含舊副本)。

  在一個變異成功寫入很久之后,組件的故障仍然可能腐化、破壞數據。GFS中,master和所有chunkserver之間會持續handshake通訊并交換信息,借此master可以識別故障的chunkserver并且通過檢查checksum偵測數據腐化(章節5.2)。一旦發現此問題,會盡快執行一個restore,從合法的副本復制合法數據替代腐化副本(章節4.3)。一個chunk也可能發生不可逆的丟失,那就是在GFS反應過來采取措施之前,所有副本都被丟失。通常GFS在分鐘內就能反應。即使出現這種天災,chunk也只是變得不可用,而不會腐化:應用收到清晰的錯誤而不是錯誤的數據。

  【譯者注】一致性的問題介紹起來難免晦澀枯燥,下面譯者用一些比較淺顯的例子來解釋GFS中的一致、不一致、defined、undefined四種狀態。

  讀者可以想象這樣一個場景,某人和他老婆共用同一個Facebook賬號,同時登陸,同時看到某張照片,他希望將其順時針旋轉90度,他老婆希望將其逆時針旋轉90度。兩人同時點了修改按鈕,Facebook應該聽誰的?俗話說意見相同聽老公的,意見不同聽老婆的。但是Facebook不懂這個算法,當他們重新打開頁面時可能會:1. 都看到圖片順時針旋轉了90度;2. 都看到圖片逆時針旋轉了90度;3. 其他情況。對于1、2兩種情況,都是可以接受的,小夫妻若來投訴那只能如實相告讓他們自己回去猜拳,不關Facebook的事兒。因為1、2既滿足一致性(兩人在并發修改發生后都一直看到一致相同的內容),又滿足defined(內容是其中一人寫入的完整數據)。對于3會有哪些其他情況呢?如果這事兒發生在單臺電腦的本地硬盤(相當于兩人同時打開一個圖片軟件、編輯同一個圖片、然后并發提交保存),若不加鎖讓其串行,則可能導致數據碎片,以簡單的代碼為例:

File file = new File("D:/temp.txt");FileOutputStream fos1 = new FileOutputStream(file);FileOutputStream fos2 = new FileOutputStream(file);fos1.write('1');fos1.write('2');fos1.write('3');fos2.write('a');fos2.write('b');fos2.write('c');fos1.close();fos2.close();

it知識庫經典論文翻譯導讀之《Google File System》,轉載需保留來源!

鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。

主站蜘蛛池模板: 中文字幕一区中文亚洲 | 亚洲一区精品中文字幕 | 国产99视频精品免费视频免里 | 高清国产美女一级毛片 | 精品日韩欧美一区二区三区在线播放 | 精品视频99| 91麻豆国产视频 | 国产高清视频在线 | 91成人高清在线播放 | 免费一级做a爰片性色毛片 免费一看一级毛片人 | 中文字幕一区二区三区精彩视频 | 亚洲一区二区三区精品国产 | 国内精品亚洲 | 亚洲一区二区免费看 | www.91自拍 | 91在线公开视频 | 久久久中文字幕 | 99re66精品视频在线观看 | 99国产成人高清在线视频 | 99pao在线视频成精品 | 激情网站网址 | 无套国产 | 日日噜噜噜噜人人爽亚洲精品 | 国产在线观看色 | 亚洲免费视频一区二区三区 | 亚洲精品乱码蜜桃久久久 | 国产欧美一区二区三区在线看 | 日韩中文字幕免费在线观看 | 中文字幕一区二区三区四区 | 日韩精品一区二区三区在线观看 | 国产激情图片 | 免费人成a大片在线观看动漫 | 好吊妞视频这里只有精品 | 亚洲成年 | 日韩视频精品在线 | 中文字幕久热精品视频免费 | 香蕉在线视频网站 | 极品美女国产精品免费一区 | 中文国产成人精品久久水 | 91精品国产9l久久久久 | 欧洲女人性开放免费网站 |