谷歌三大核心技術(一)Google File System中文版
The Google File System中文版
譯者:alex摘要
我們設計並實現了Google GFS檔案系統,一個面向大規模資料密集型應用的、可伸縮的分散式檔案系統。GFS雖然執行在廉價的普遍硬體裝置上,但是它依然了提供災難冗餘的能力,為大量客戶機提供了高效能的服務。 雖然GFS的設計目標與許多傳統的分散式檔案系統有很多相同之處,但是,我們的設計還是以我們對自己的應用的負載情況和技術環境的分析為基礎 的,不管現在還是將來,GFS和早期的分散式檔案系統的設想都有明顯的不同。所以我們重新審視了傳統檔案系統在設計上的折衷選擇,衍生出了完全不同的設計 思路。 GFS完全滿足了我們對儲存的需求。GFS作為儲存平臺已經被廣泛的部署在Google內部,儲存我們的服務產生和處理的資料,同時還用於那些 需要大規模資料集的研究和開發工作。目前為止,最大的一個叢集利用數千臺機器的數千個硬碟,提供了數百TB的儲存空間,同時為數百個客戶機服務。 在本論文中,我們展示了能夠支援分散式應用的檔案系統介面的擴充套件,討論我們設計的許多方面,最後列出了小規模效能測試以及真實生產系統中效能相關資料。分類和主題描述
常用術語
設計,可靠性,效能,測量關鍵詞
容錯,可伸縮性,資料儲存,叢集儲存1. 簡介
為了滿足Google迅速增長的資料處理需求,我們設計並實現了Google檔案系統(Google File System – GFS)。GFS與傳統的分散式檔案系統有著很多相同的設計目標,比如,效能、可伸縮性、可靠性以及可用性。但是,我們的設計還基於我們對我們自己的應用 的負載情況和技術環境的觀察的影響,不管現在還是將來,GFS和早期檔案系統的假設都有明顯的不同。所以我們重新審視了傳統檔案系統在設計上的折衷選擇, 衍生出了完全不同的設計思路。 首先,元件失效被認為是常態事件,而不是意外事件。GFS包括幾百甚至幾千臺普通的廉價裝置組裝的儲存機器,同時被相當數量的客戶機訪問。 GFS元件的數量和質量導致在事實上,任何給定時間內都有可能發生某些元件無法工作,某些元件無法從它們目前的失效狀態中恢復。我們遇到過各種各樣的問 題,比如應用程式bug、作業系統的bug、人為失誤,甚至還有硬碟、記憶體、聯結器、網路以及電源失效等造成的問題。所以,持續的監控、錯誤偵測、災難冗 餘以及自動恢復的機制必須整合在GFS中。 其次,以通常的標準衡量,我們的檔案非常巨大。數GB的檔案非常普遍。每個檔案通常都包含許多應用程式物件,比如web文件。當我們經常需要處 理快速增長的、並且由數億個物件構成的、數以TB的資料集時,採用管理數億個KB大小的小檔案的方式是非常不明智的,儘管有些檔案系統支援這樣的管理方 式。因此,設計的假設條件和引數,比如I/O操作和Block的尺寸都需要重新考慮。 第三,絕大部分檔案的修改是採用在檔案尾部追加資料,而不是覆蓋原有資料的方式。對檔案的隨機寫入操作在實際中幾乎不存在。一旦寫完之後,對文 件的操作就只有讀,而且通常是按順序讀。大量的資料符合這些特性,比如:資料分析程式掃描的超大的資料集;正在執行的應用程式生成的連續的資料流;存檔的 資料;由一臺機器生成、另外一臺機器處理的中間資料,這些中間資料的處理可能是同時進行的、也可能是後續才處理的。對於這種針對海量檔案的訪問模式,客戶 端對資料塊快取是沒有意義的,資料的追加操作是效能優化和原子性保證的主要考量因素。 第四,應用程式和檔案系統API的協同設計提高了整個系統的靈活性。比如,我們放鬆了對GFS一致性模型的要求,這樣就減輕了檔案系統對應用程 序的苛刻要求,大大簡化了GFS的設計。我們引入了原子性的記錄追加操作,從而保證多個客戶端能夠同時進行追加操作,不需要額外的同步操作來保證資料的一 致性。本文後面還有對這些問題的細節的詳細討論。 Google已經針對不同的應用部署了多套GFS叢集。最大的一個叢集擁有超過1000個儲存節點,超過300TB的硬碟空間,被不同機器上的數百個客戶端連續不斷的頻繁訪問。2.設計概述
2.1設計預期
在設計滿足我們需求的檔案系統時候,我們的設計目標既有機會、又有挑戰。之前我們已經提到了一些需要關注的關鍵點,這裡我們將設計的預期目標的細節展開討論。
- 系統由許多廉價的普通元件組成,元件失效是一種常態。系統必須持續監控自身的狀態,它必須將元件失效作為一種常態,能夠迅速地偵測、冗餘並恢復失效的元件。
- 系統儲存一定數量的大檔案。我們預期會有幾百萬檔案,檔案的大小通常在100MB或者以上。數個GB大小的檔案也是普遍存在,並且要能夠被有效的管理。系統也必須支援小檔案,但是不需要針對小檔案做專門的優化。
- 系統的工作負載主要由兩種讀操作組成:大規模的流式讀取和小規模的隨機讀取。大規模的流式讀取通常一次讀取數百KB的資料,更常見的是一次讀取 1MB甚至更多的資料。來自同一個客戶機的連續操作通常是讀取同一個檔案中連續的一個區域。小規模的隨機讀取通常是在檔案某個隨機的位置讀取幾個KB數 據。如果應用程式對效能非常關注,通常的做法是把小規模的隨機讀取操作合併並排序,之後按順序批量讀取,這樣就避免了在檔案中前後來回的移動讀取位置。
- 系統的工作負載還包括許多大規模的、順序的、資料追加方式的寫操作。一般情況下,每次寫入的資料的大小和大規模讀類似。資料一旦被寫入後,檔案就很少會被修改了。系統支援小規模的隨機位置寫入操作,但是可能效率不彰。
- 系統必須高效的、行為定義明確的 (alex注:well-defined)實現多 客戶端並行追加資料到同一個檔案裡的語意。我們的檔案通常被用於”生產者-消費者“佇列,或者其它多路檔案合併操作。通常會有數百個生產者,每個生產者進 程執行在一臺機器上,同時對一個檔案進行追加操作。使用最小的同步開銷來實現的原子的多路追加資料操作是必不可少的。檔案可以在稍後讀取,或者是消費者在 追加的操作的同時讀取檔案。
- 高效能的穩定網路頻寬遠比低延遲重要。我們的目標程式絕大部分要求能夠高速率的、大批量的處理資料,極少有程式對單一的讀寫操作有嚴格的響應時間要求。
2.2 介面
GFS提供了一套類似傳統檔案系統的API介面函式,雖然並不是嚴格按照POSIX等標準API的形式實現的。檔案以分層目錄的形式組織,用路徑名來標識。我們支援常用的操作,如建立新檔案、刪除檔案、開啟檔案、關閉檔案、讀和寫檔案。 另外,GFS提供了快照和記錄追加操作。快照以很低的成本建立一個檔案或者目錄樹的拷貝。記錄追加操作允許多個客戶端同時對一個檔案進行資料追 加操作,同時保證每個客戶端的追加操作都是原子性的。這對於實現多路結果合併,以及”生產者-消費者”佇列非常有用,多個客戶端可以在不需要額外的同步鎖 定的情況下,同時對一個檔案追加資料。我們發現這些型別的檔案對於構建大型分佈應用是非常重要的。快照和記錄追加操作將在3.4和3.3節分別討論。2.3 架構
一個GFS叢集包含一個單獨的Master節點 (alex注:這裡的一個單 獨的Master節點的含義是GFS系統中只存在一個邏輯上的Master元件。後面我們還會提到Master節點複製,因此,為了理解方便,我們把 Master節點視為一個邏輯上的概念,一個邏輯的Master節點包括兩臺物理主機,即兩臺Master伺服器)、多臺 Chunk伺服器,並且同時被多個客戶端訪問,如圖1所示。所有的這些機器通常都是普通的Linux機器,執行著使用者級別(user-level)的服務 程序。我們可以很容易的把Chunk伺服器和客戶端都放在同一臺機器上,前提是機器資源允許,並且我們能夠接受不可靠的應用程式程式碼帶來的穩定性降低的風 險。 GFS儲存的檔案都被分割成固定大小的Chunk。在Chunk建立的時候,Master伺服器會給每個Chunk分配一個不變的、全球唯一的 64位的Chunk標識。Chunk伺服器把Chunk以linux檔案的形式儲存在本地硬碟上,並且根據指定的Chunk標識和位元組範圍來讀寫塊資料。 出於可靠性的考慮,每個塊都會複製到多個塊伺服器上。預設情況下,我們使用3個儲存複製節點,不過使用者可以為不同的檔案名稱空間設定不同的複製級別。 Master節點管理所有的檔案系統元資料。這些元資料包括名字空間、訪問控制資訊、檔案和Chunk的對映資訊、以及當前Chunk的位置資訊。Master節點還管理著系統範圍內的活動,比如,Chunk租用管理 (alex注:BDB也有關於lease的描述,不知道是否相同)、孤兒Chunk (alex注:orphaned chunks)的回收、以及Chunk在Chunk伺服器之間的遷移。Master節點使用心跳資訊週期地和每個Chunk伺服器通訊,傳送指令到各個Chunk伺服器並接收Chunk伺服器的狀態資訊。 GFS客戶端程式碼以庫的形式被連結到客戶程式裡。客戶端程式碼實現了GFS檔案系統的API介面函式、應用程式與Master節點和Chunk服 務器通訊、以及對資料進行讀寫操作。客戶端和Master節點的通訊只獲取元資料,所有的資料操作都是由客戶端直接和Chunk伺服器進行互動的。我們不 提供POSIX標準的API的功能,因此,GFS API呼叫不需要深入到Linux vnode級別。 無論是客戶端還是Chunk伺服器都不需要快取檔案資料。客戶端快取資料幾乎沒有什麼用處,因為大部分程式要麼以流的方式讀取一個巨大檔案,要 麼工作集太大根本無法被快取。無需考慮快取相關的問題也簡化了客戶端和整個系統的設計和實現。(不過,客戶端會快取元資料。)Chunk伺服器不需要快取 檔案資料的原因是,Chunk以本地檔案的方式儲存,Linux作業系統的檔案系統快取會把經常訪問的資料快取在記憶體中。2.4 單一Master節點
單一的Master節點的策略大大簡化了我們的設計。單一的Master節點可以通過全域性的資訊精確定位Chunk的位置以及進行復制決策。另 外,我們必須減少對Master節點的讀寫,避免Master節點成為系統的瓶頸。客戶端並不通過Master節點讀寫檔案資料。反之,客戶端向 Master節點詢問它應該聯絡的Chunk伺服器。客戶端將這些元資料資訊快取一段時間,後續的操作將直接和Chunk伺服器進行資料讀寫操作。 我們利用圖1解釋一下一次簡單讀取的流程。首先,客戶端把檔名和程式指定的位元組偏移,根據固定的Chunk大小,轉換成檔案的Chunk索 引。然後,它把檔名和Chunk索引發送給Master節點。Master節點將相應的Chunk標識和副本的位置資訊發還給客戶端。客戶端用檔名和 Chunk索引作為key快取這些資訊。 之後客戶端傳送請求到其中的一個副本處,一般會選擇最近的。請求資訊包含了Chunk的標識和位元組範圍。在對這個Chunk的後續讀取操作中, 客戶端不必再和Master節點通訊了,除非快取的元資料資訊過期或者檔案被重新開啟。實際上,客戶端通常會在一次請求中查詢多個Chunk信 息,Master節點的迴應也可能包含了緊跟著這些被請求的Chunk後面的Chunk的資訊。在實際應用中,這些額外的資訊在沒有任何代價的情況下,避 免了客戶端和Master節點未來可能會發生的幾次通訊。2.5 Chunk尺寸
Chunk的大小是關鍵的設計引數之一。我們選擇了64MB,這個尺寸遠遠大於一般檔案系統的Block size。每個Chunk的副本都以普通Linux檔案的形式儲存在Chunk伺服器上,只有在需要的時候才擴大。惰性空間分配策略避免了因內部碎片造成 的空間浪費,內部碎片或許是對選擇這麼大的Chunk尺寸最具爭議一點。 選擇較大的Chunk尺寸有幾個重要的優點。首先,它減少了客戶端和Master節點通訊的需求,因為只需要一次和Mater節點的通訊就可以 獲取Chunk的位置資訊,之後就可以對同一個Chunk進行多次的讀寫操作。這種方式對降低我們的工作負載來說效果顯著,因為我們的應用程式通常是連續 讀寫大檔案。即使是小規模的隨機讀取,採用較大的Chunk尺寸也帶來明顯的好處,客戶端可以輕鬆的快取一個數TB的工作資料集所有的Chunk位置信 息。其次,採用較大的Chunk尺寸,客戶端能夠對一個塊進行多次操作,這樣就可以通過與Chunk伺服器保持較長時間的TCP連線來減少網路負載。第 三,選用較大的Chunk尺寸減少了Master節點需要儲存的元資料的數量。這就允許我們把元資料全部放在記憶體中,在2.6.1節我們會討論元資料全部 放在記憶體中帶來的額外的好處。 另一方面,即使配合惰性空間分配,採用較大的Chunk尺寸也有其缺陷。小檔案包含較少的Chunk,甚至只有一個Chunk。當有許多的客戶 端對同一個小檔案進行多次的訪問時,儲存這些Chunk的Chunk伺服器就會變成熱點。在實際應用中,由於我們的程式通常是連續的讀取包含多個 Chunk的大檔案,熱點還不是主要的問題。 然而,當我們第一次把GFS用於批處理佇列系統的時候,熱點的問題還是產生了:一個可執行檔案在GFS上儲存為single-chunk檔案, 之後這個可執行檔案在數百臺機器上同時啟動。存放這個可執行檔案的幾個Chunk伺服器被數百個客戶端的併發請求訪問導致系統區域性過載。我們通過使用更大 的複製引數來儲存可執行檔案,以及錯開批處理佇列系統程式的啟動時間的方法解決了這個問題。一個可能的長效解決方案是,在這種的情況下,允許客戶端從其它 客戶端讀取資料。2.6 元資料
Master伺服器 (alex注:注意邏輯的Master節點和物理的Master伺服器的區別。後續我們談的是每個Master伺服器的行為,如儲存、記憶體等等,因此我們將全部使用物理名稱)存 儲3種主要型別的元資料,包括:檔案和Chunk的名稱空間、檔案和Chunk的對應關係、每個Chunk副本的存放地點。所有的元資料都儲存在 Master伺服器的記憶體中。前兩種型別的元資料(名稱空間、檔案和Chunk的對應關係)同時也會以記錄變更日誌的方式記錄在作業系統的系統日誌檔案 中,日誌檔案儲存在本地磁碟上,同時日誌會被複制到其它的遠端Master伺服器上。採用儲存變更日誌的方式,我們能夠簡單可靠的更新Master伺服器 的狀態,並且不用擔心Master伺服器崩潰導致資料不一致的風險。Master伺服器不會持久儲存Chunk位置資訊。Master伺服器在啟動時,或 者有新的Chunk伺服器加入時,向各個Chunk伺服器輪詢它們所儲存的Chunk的資訊。2.6.1 記憶體中的資料結構
因為元資料儲存在記憶體中,所以Master伺服器的操作速度非常快。並且,Master伺服器可以在後臺簡單而高效的週期性掃描自己儲存的全部 狀態資訊。這種週期性的狀態掃描也用於實現Chunk垃圾收集、在Chunk伺服器失效的時重新複製資料、通過Chunk的遷移實現跨Chunk伺服器的 負載均衡以及磁碟使用狀況統計等功能。4.3和4.4章節將深入討論這些行為。 將元資料全部儲存在記憶體中的方法有潛在問題:Chunk的數量以及整個系統的承載能力都受限於Master伺服器所擁有的記憶體大小。但是在實際 應用中,這並不是一個嚴重的問題。Master伺服器只需要不到64個位元組的元資料就能夠管理一個64MB的Chunk。由於大多數檔案都包含多個 Chunk,因此絕大多數Chunk都是滿的,除了檔案的最後一個Chunk是部分填充的。同樣的,每個檔案的在名稱空間中的資料大小通常在64位元組以 下,因為儲存的檔名是用字首壓縮演算法壓縮過的。 即便是需要支援更大的檔案系統,為Master伺服器增加額外記憶體的費用是很少的,而通過增加有限的費用,我們就能夠把元資料全部儲存在記憶體裡,增強了系統的簡潔性、可靠性、高效能和靈活性。2.6.2 Chunk位置資訊
Master伺服器並不儲存持久化儲存哪個Chunk伺服器存有指定Chunk的副本的資訊。Master伺服器只是在啟動的時候輪詢Chunk服 務器以獲取這些資訊。Master伺服器能夠保證它持有的資訊始終是最新的,因為它控制了所有的Chunk位置的分配,而且通過週期性的心跳資訊監控 Chunk伺服器的狀態。
最初設計時,我們試圖把Chunk的位置資訊持久的儲存在Master伺服器上,但是後來我們發現在啟動的時候輪詢Chunk伺服器,之後定期輪詢 更新的方式更簡單。這種設計簡化了在有Chunk伺服器加入叢集、離開叢集、更名、失效、以及重啟的時候,Master伺服器和Chunk伺服器資料同步 的問題。在一個擁有數百臺伺服器的叢集中,這類事件會頻繁的發生。
可以從另外一個角度去理解這個設計決策:只有Chunk伺服器才能最終確定一個Chunk是否在它的硬碟上。我們從沒有考慮過在Master伺服器 上維護一個這些資訊的全域性檢視,因為Chunk伺服器的錯誤可能會導致Chunk自動消失(比如,硬碟損壞了或者無法訪問了),亦或者操作人員可能會重命 名一個Chunk伺服器。
2.6.3 操作日誌
操作日誌包含了關鍵的元資料變更歷史記錄。這對GFS非常重要。這不僅僅是因為操作日誌是元資料唯一的持久化儲存記錄,它也作為判斷同步操作順序的邏輯時間基線(alex注:也就是通過邏輯日誌的序號作為操作發生的邏輯時間,類似於事務系統中的LSN)。檔案和Chunk,連同它們的版本(參考4.5節),都由它們建立的邏輯時間唯一的、永久的標識。
操作日誌非常重要,我們必須確保日誌檔案的完整,確保只有在元資料的變化被持久化後,日誌才對客戶端是可見的。否則,即使Chunk本身沒有出現任 何問題,我們仍有可能丟失整個檔案系統,或者丟失客戶端最近的操作。所以,我們會把日誌複製到多臺遠端機器,並且只有把相應的日誌記錄寫入到本地以及遠端 機器的硬碟後,才會響應客戶端的操作請求。Master伺服器會收集多個日誌記錄後批量處理,以減少寫入磁碟和複製對系統整體效能的影響。
Master伺服器在災難恢復時,通過重演操作日誌把檔案系統恢復到最近的狀態。為了縮短Master啟動的時間,我們必須使日誌足夠小 (alex注:即重演系統操作的日誌量儘量的少)。Master伺服器在日誌增長到一定量時對系統狀態做一次Checkpoint (alex注:Checkpoint是一種行為,一種對資料庫狀態作一次快照的行為),將所有的狀態資料寫入一個Checkpoint檔案 (alex注:並刪除之前的日誌檔案)。 在災難恢復的時候,Master伺服器就通過從磁碟上讀取這個Checkpoint檔案,以及重演Checkpoint之後的有限個日誌檔案就能夠恢復系統。Checkpoint檔案以壓縮B-樹形勢的資料結構儲存,可以直接對映到記憶體,在用於名稱空間查詢時無需額外的解析。這大大提高了恢復速度,增強了可用性。由於建立一個Checkpoint檔案需要一定的時間,所以Master伺服器的內部狀態被組織為一種格式,這種格式要確保在Checkpoint 過程中不會阻塞正在進行的修改操作。Master伺服器使用獨立的執行緒切換到新的日誌檔案和建立新的Checkpoint檔案。新的Checkpoint 檔案包括切換前所有的修改。對於一個包含數百萬個檔案的叢集,建立一個Checkpoint檔案需要1分鐘左右的時間。建立完成後,Checkpoint 檔案會被寫入在本地和遠端的硬盤裡。
Master伺服器恢復只需要最新的Checkpoint檔案和後續的日誌檔案。舊的Checkpoint檔案和日誌檔案可以被刪除,但是為了應對災難性的故障(alex注:catastrophes,資料備份相關文件中經常會遇到這個詞,表示一種超出預期範圍的災難性事件),我們通常會多儲存一些歷史檔案。Checkpoint失敗不會對正確性產生任何影響,因為恢復功能的程式碼可以檢測並跳過沒有完成的Checkpoint檔案。
2.7 一致性模型
GFS支援一個寬鬆的一致性模型,這個模型能夠很好的支撐我們的高度分佈的應用,同時還保持了相對簡單且容易實現的優點。本節我們討論GFS的一致 性的保障機制,以及對應用程式的意義。我們也著重描述了GFS如何管理這些一致性保障機制,但是實現的細節將在本論文的其它部分討論。
2.7.1 GFS一致性保障機制
檔案名稱空間的修改(例如,檔案建立)是原子性的。它們僅由Master節點的控制:名稱空間鎖提供了原子性和正確性(4.1章)的保障;Master節點的操作日誌定義了這些操作在全域性的順序(2.6.3章)。
資料修改後檔案region(alex注:region這個詞用中文非常難以表達,我認為應該是修改操作所涉及的檔案中的某個範圍)的 狀態取決於操作的型別、成功與否、以及是否同步修改。表1總結了各種操作的結果。如果所有客戶端,無論從哪個副本讀取,讀到的資料都一樣,那麼我們認為文 件region是“一致的”;如果對檔案的資料修改之後,region是一致的,並且客戶端能夠看到寫入操作全部的內容,那麼這個region是“已定義 的”。當一個數據修改操作成功執行,並且沒有受到同時執行的其它寫入操作的干擾,那麼影響的region就是已定義的(隱含了一致性):所有的客戶端都可 以看到寫入的內容。並行修改操作成功完成之後,region處於一致的、未定義的狀態:所有的客戶端看到同樣的資料,但是無法讀到任何一次寫入操作寫入的 資料。通常情況下,檔案region內包含了來自多個修改操作的、混雜的資料片段。失敗的修改操作導致一個region處於不一致狀態(同時也是未定義 的):不同的客戶在不同的時間會看到不同的資料。後面我們將描述應用如何區分已定義和未定義的region。應用程式沒有必要再去細分未定義region 的不同型別。
資料修改操作分為寫入或者記錄追加兩種。寫入操作把資料寫在應用程式指定的檔案偏移位置上。即使有多個修改操作並行執行時,記錄追加操作至少可以把資料原子性的追加到檔案中一次,但是偏移位置是由GFS選擇的(3.3章) (alex注:這句話有點費解,其含義是所有的追加寫入都會成功,但是有可能被執行了多次,而且每次追加的檔案偏移量由GFS自己計算)。 (相比而言,通常說的追加操作寫的偏移位置是檔案的尾部。)GFS返回給客戶端一個偏移量,表示了包含了寫入記錄的、已定義的region的起點。另 外,GFS可能會在檔案中間插入填充資料或者重複記錄。這些資料佔據的檔案region被認定是不一致的,這些資料通常比使用者資料小的多。經過了一系列的成功的修改操作之後,GFS確保被修改的檔案region是已定義的,並且包含最後一次修改操作寫入的資料。GFS通過以下措施確保 上述行為:(a) 對Chunk的所有副本的修改操作順序一致(3.1章),(b)使用Chunk的版本號來檢測副本是否因為它所在的Chunk伺服器宕機(4.5章)而錯 過了修改操作而導致其失效。失效的副本不會再進行任何修改操作,Master伺服器也不再返回這個Chunk副本的位置資訊給客戶端。它們會被垃圾收集系 統儘快回收。
由於Chunk位置資訊會被客戶端快取,所以在資訊重新整理前,客戶端有可能從一個失效的副本讀取了資料。在快取的超時時間和檔案下一次被開啟的時 間之間存在一個時間窗,檔案再次被開啟後會清除快取中與該檔案有關的所有Chunk位置資訊。而且,由於我們的檔案大多數都是隻進行追加操作的,所以,一 個失效的副本通常返回一個提前結束的Chunk而不是過期的資料。當一個Reader (alex注:本文中將用到兩個專有名詞,Reader和Writer,分別表示執行GFS讀取和寫入操作的程式)重新嘗試並聯絡Master伺服器時,它就會立刻得到最新的Chunk位置資訊。 即使在修改操作成功執行很長時間之後,元件的失效也可能損壞或者刪除資料。GFS通過Master伺服器和所有Chunk伺服器的定期“握手” 來找到失效的Chunk伺服器,並且使用Checksum來校驗資料是否損壞(5.2章)。一旦發現問題,資料要儘快利用有效的副本進行恢復(4.3 章)。只有當一個Chunk的所有副本在GFS檢測到錯誤並採取應對措施之前全部丟失,這個Chunk才會不可逆轉的丟失。在一般情況下GFS的反應時間 (alex注:指Master節點檢測到錯誤並採取應對措施)是幾分鐘。即使在這種情況下,Chunk也只是不可用了,而不是損壞了:應用程式會收到明確的錯誤資訊而不是損壞的資料。2.7.2 程式的實現
使用GFS的應用程式可以利用一些簡單技術實現這個寬鬆的一致性模型,這些技術也用來實現一些其它的目標功能,包括:儘量採用追加寫入而不是覆蓋,Checkpoint,自驗證的寫入操作,自標識的記錄。 在實際應用中,我們所有的應用程式對檔案的寫入操作都是儘量採用資料追加方式,而不是覆蓋方式。一種典型的應用,應用程式從頭到尾寫入資料,生 成了一個檔案。寫入所有資料之後,應用程式自動將檔案改名為一個永久儲存的檔名,或者週期性的作Checkpoint,記錄成功寫入了多少資料。 Checkpoint檔案可以包含程式級別的校驗和。Readers僅校驗並處理上個Checkpoint之後產生的檔案region,這些檔案 region的狀態一定是已定義的。這個方法滿足了我們一致性和併發處理的要求。追加寫入比隨機位置寫入更加有效率,對應用程式的失敗處理更具有彈性。 Checkpoint可以讓Writer以漸進的方式重新開始,並且可以防止Reader處理已經被成功寫入,但是從應用程式的角度來看還並未完成的數 據。 我們再來分析另一種典型的應用。許多應用程式並行的追加資料到同一個檔案,比如進行結果的合併或者是一個生產者-消費者佇列。記錄追加方式的 “至少一次追加”的特性保證了Writer的輸出。Readers使用下面的方法來處理偶然性的填充資料和重複內容。Writers在每條寫入的記錄中都 包含了額外的資訊,例如Checksum,用來驗證它的有效性。Reader可以利用Checksum識別和拋棄額外的填充資料和記錄片段。如果應用不能 容忍偶爾的重複內容(比如,如果這些重複資料觸發了非冪等操作),可以用記錄的唯一識別符號來過濾它們,這些唯一識別符號通常用於命名程式中處理的實體物件, 例如web文件。這些記錄I/O功能 (alex注:These functionalities for record I/O)(除了剔除重複資料)都包含在我們的程式共享的庫中,並且適用於Google內部的其它的檔案介面實現。所以,相同序列的記錄,加上一些偶爾出現的重複資料,都被分發到Reader了。3. 系統互動
我們在設計這個系統時,一個重要的原則是最小化所有操作和Master節點的互動。帶著這樣的設計理念,我們現在描述一下客戶機、Master伺服器和Chunk伺服器如何進行互動,以實現資料修改操作、原子的記錄追加操作以及快照功能。3.1 租約(lease)和變更順序
(alex注:lease是資料庫中的一個術語)
變更是一個會改變Chunk內容或者元資料的操作,比如寫入操作或者記錄追加操作。變更操作會在Chunk的所有副本上執行。我們使用租約 (lease)機制來保持多個副本間變更順序的一致性。Master節點為Chunk的一個副本建立一個租約,我們把這個副本叫做主Chunk。主 Chunk對Chunk的所有更改操作進行序列化。所有的副本都遵從這個序列進行修改操作。因此,修改操作全域性的順序首先由Master節點選擇的租約的 順序決定,然後由租約中主Chunk分配的序列號決定。
設計租約機制的目的是為了最小化Master節點的管理負擔。租約的初始超時設定為60秒。不過,只要Chunk被修改了,主Chunk就可以 申請更長的租期,通常會得到Master節點的確認並收到租約延長的時間。這些租約延長請求和批准的資訊通常都是附加在Master節點和Chunk服務 器之間的心跳訊息中來傳遞。有時Master節點會試圖提前取消租約(例如,Master節點想取消在一個已經被改名的檔案上的修改操作)。即使 Master節點和主Chunk失去聯絡,它仍然可以安全地在舊的租約到期後和另外一個Chunk副本簽訂新的租約。在圖2中,我們依據步驟編號,展現寫入操作的控制流程。
- 客戶機向Master節點詢問哪一個Chunk伺服器持有當前的租約,以及其它副本的位置。如果沒有一個Chunk持有租約,Master節點就選擇其中一個副本建立一個租約(這個步驟在圖上沒有顯示)。
- Master節點將主Chunk的識別符號以及其它副本(又稱為secondary副本、二級副本)的位置返回給客戶機。客戶機快取這些資料以便 後續的操作。只有在主Chunk不可用,或者主Chunk回覆資訊表明它已不再持有租約的時候,客戶機才需要重新跟Master節點聯絡。
- 客戶機把資料推送到所有的副本上。客戶機可以以任意的順序推送資料。Chunk伺服器接收到資料並儲存在它的內部LRU快取中,一直到資料被使 用或者過期交換出去。由於資料流的網路傳輸負載非常高,通過分離資料流和控制流,我們可以基於網路拓撲情況對資料流進行規劃,提高系統性能,而不用去理會 哪個Chunk伺服器儲存了主Chunk。3.2章節會進一步討論這點。
- 當所有的副本都確認接收到了資料,客戶機發送寫請求到主Chunk伺服器。這個請求標識了早前推送到所有副本的資料。主Chunk為接收到的所 有操作分配連續的序列號,這些操作可能來自不同的客戶機,序列號保證了操作順序執行。它以序列號的順序把操作應用到它自己的本地狀態中 (alex注:也就是在本地執行這些操作,這句話按字面翻譯有點費解,也許應該翻譯為“它順序執行這些操作,並更新自己的狀態”)。
- 主Chunk把寫請求傳遞到所有的二級副本。每個二級副本依照主Chunk分配的序列號以相同的順序執行這些操作。
- 所有的二級副本回復主Chunk,它們已經完成了操作。
- 主Chunk伺服器 (alex注:即主Chunk所在的Chunk伺服器)回 復客戶機。任何副本產生的任何錯誤都會返回給客戶機。在出現錯誤的情況下,寫入操作可能在主Chunk和一些二級副本執行成功。(如果操作在主Chunk 上失敗了,操作就不會被分配序列號,也不會被傳遞。)客戶端的請求被確認為失敗,被修改的region處於不一致的狀態。我們的客戶機程式碼通過重複執行失 敗的操作來處理這樣的錯誤。在從頭開始重複執行之前,客戶機會先從步驟(3)到步驟(7)做幾次嘗試。
3.2 資料流
為了提高網路效率,我們採取了把資料流和控制流分開的措施。在控制流從客戶機到主Chunk、然後再到所有二級副本的同時,資料以管道的方式, 順序的沿著一個精心選擇的Chunk伺服器鏈推送。我們的目標是充分利用每臺機器的頻寬,避免網路瓶頸和高延時的連線,最小化推送所有資料的延時。 為了充分利用每臺機器的頻寬,資料沿著一個Chunk伺服器鏈順序的推送,而不是以其它拓撲形式分散推送(例如,樹型拓撲結構)。線性推送模式下,每臺機器所有的出口頻寬都用於以最快的速度傳輸資料,而不是在多個接受者之間分配頻寬。 為了儘可能的避免出現網路瓶頸和高延遲的連結(eg,inter-switch最有可能出現類似問題),每臺機器都儘量的在網路拓撲中選擇一臺 還沒有接收到資料的、離自己最近的機器作為目標推送資料。假設客戶機把資料從Chunk伺服器S1推送到S4。它把資料推送到最近的Chunk伺服器 S1。S1把資料推送到S2,因為S2和S4中最接近的機器是S2。同樣的,S2把資料傳遞給S3和S4之間更近的機器,依次類推推送下去。我們的網路拓 撲非常簡單,通過IP地址就可以計算出節點的“距離”。 最後,我們利用基於TCP連線的、管道式資料推送方式來最小化延遲。Chunk伺服器接收到資料後,馬上開始向前推送。管道方式的資料推送對我 們幫助很大,因為我們採用全雙工的交換網路。接收到資料後立刻向前推送不會降低接收的速度。在沒有網路擁塞的情況下,傳送B位元組的資料到R個副本的理想時 間是 B/T+RL ,T是網路的吞吐量,L是在兩臺機器資料傳輸的延遲。通常情況下,我們的網路連線速度是100Mbps(T),L將遠小於1ms。因此,1MB的資料在理 想情況下80ms左右就能分發出去。3.3 原子的記錄追加
GFS提供了一種原子的資料追加操作–記錄追加。傳統方式的寫入操作,客戶程式會指定資料寫入的偏移量。對同一個region的並行寫入操作不 是序列的:region尾部可能會包含多個不同客戶機寫入的資料片段。使用記錄追加,客戶機只需要指定要寫入的資料。GFS保證至少有一次原子的寫入操作 成功執行(即寫入一個順序的byte流),寫入的資料追加到GFS指定的偏移位置上,之後GFS返回這個偏移量給客戶機。這類似於在Unix作業系統程式設計 環境中,對以O_APPEND模式開啟的檔案,多個併發寫操作在沒有競態條件時的行為。 記錄追加在我們的分佈應用中非常頻繁的使用,在這些分散式應用中,通常有很多的客戶機並行地對同一個檔案追加寫入資料。如果我們採用傳統方式的 檔案寫入操作,客戶機需要額外的複雜、昂貴的同步機制,例如使用一個分散式的鎖管理器。在我們的工作中,這樣的檔案通常用於多個生產者/單一消費者的佇列 系統,或者是合併了來自多個客戶機的資料的結果檔案。 記錄追加是一種修改操作,它也遵循3.1節描述的控制流程,除了在主Chunk有些額外的控制邏輯。客戶機把資料推送給檔案最後一個Chunk 的所有副本,之後傳送請求給主Chunk。主Chunk會檢查這次記錄追加操作是否會使Chunk超過最大尺寸(64MB)。如果超過了最大尺寸,主 Chunk首先將當前Chunk填充到最大尺寸,之後通知所有二級副本做同樣的操作,然後回覆客戶機要求其對下一個Chunk重新進行記錄追加操作。(記 錄追加的資料大小嚴格控制在Chunk最大尺寸的1/4,這樣即使在最壞情況下,資料碎片的數量仍然在可控的範圍。)通常情況下追加的記錄不超過 Chunk的最大尺寸,主Chunk把資料追加到自己的副本內,然後通知二級副本把資料寫在跟主Chunk一樣的位置上,最後回覆客戶機操作成功。 如果記錄追加操作在任何一個副本上失敗了,客戶端就需要重新進行操作。重新進行記錄追加的結果是,同一個Chunk的不同副本可能包含不同的數 據–重複包含一個記錄全部或者部分的資料。GFS並不保證Chunk的所有副本在位元組級別是完全一致的。它只保證資料作為一個整體原子的被至少寫入一次。 這個特性可以通過簡單觀察推匯出來:如果操作成功執行,資料一定已經寫入到Chunk的所有副本的相同偏移位置上。這之後,所有的副本至少都到了記錄尾部 的長度,任何後續的記錄都會追加到更大的偏移地址,或者是不同的Chunk上,即使其它的Chunk副本被Master節點選為了主Chunk。就我們的 一致性保障模型而言,記錄追加操作成功寫入資料的region是已定義的(因此也是一致的),反之則是不一致的(因此也就是未定義的)。正如我們在 2.7.2節討論的,我們的程式可以處理不一致的區域。3.4 快照
(alex注:這一節非常難以理解,總的來說依次講述了什麼是快照、快照使用的COW技術、快照如何不干擾當前操作) 快照操作幾乎可以瞬間完成對一個檔案或者目錄樹(“源”)做一個拷貝,並且幾乎不會對正在進行的其它操作造成任何干擾。我們的使用者可以使用快照 迅速的建立一個巨大的資料集的分支拷貝(而且經常是遞迴的拷貝拷貝),或者是在做實驗性的資料操作之前,使用快照操作備份當前狀態,這樣之後就可以輕鬆的 提交或者回滾到備份時的狀態。 就像AFS (alex注:AFS,即Andrew File System,一種分散式檔案系統),我 們用標準的copy-on-write技術實現快照。當Master節點收到一個快照請求,它首先取消作快照的檔案的所有Chunk的租約。這個措施保證 了後續對這些Chunk的寫操作都必須與Master互動互動以找到租約持有者。這就給Master節點一個率先建立Chunk的新拷貝的機會。 租約取消或者過期之後,Master節點把這個操作以日誌的方式記錄到硬碟上。然後,Master節點通過複製原始檔或者目錄的元資料的方式,把這條日誌記錄的變化反映到儲存在記憶體的狀態中。新建立的快照檔案和原始檔指向完全相同的Chunk地址。 在快照操作之後,當客戶機第一次想寫入資料到Chunk C,它首先會發送一個請求到Master節點查詢當前的租約持有者。Master節點注意到Chunke C的引用計數超過了1 (alex注:不太明白為什麼會大於1.難道是Snapshot沒有釋放引用計數?)。 Master節點不會馬上回復客戶機的請求,而是選擇一個新的Chunk控制代碼C`。之後,Master節點要求每個擁有Chunk C當前副本的Chunk伺服器建立一個叫做C`的新Chunk。通過在源Chunk所在Chunk伺服器上建立新的Chunk,我們確保資料在本地而不是 通過網路複製(我們的硬碟比我們的100Mb乙太網大約快3倍)。從這點來講,請求的處理方式和任何其它Chunk沒什麼不同:Master節點確保新 Chunk C`的一個副本擁有租約,之後回覆客戶機,客戶機得到回覆後就可以正常的寫這個Chunk,而不必理會它是從一個已存在的Chunk克隆出來的。4. Master節點的操作
相關推薦
谷歌三大核心技術(一)Google File System中文版
The Google File System中文版 譯者:alex 摘要 我們設計並實現了Google GFS檔案系統,一個面向大規模資料密集型應用的、可伸縮的分散式檔案系統。GFS雖然執行在廉價的普遍硬體裝置上,但是它依然了提供災難冗餘的能力,為大
谷歌三大核心技術(一)Google File System
We wish to thankt he following people for their contributions to the system or the paper. Brain Bershad (our shepherd) and the anonymous reviewers gave us
谷歌三大核心技術(三)Google BigTable中文版
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
谷歌三大核心技術(二)Google MapReduce中文版
Google MapReduce中文版 譯者: alex 摘要 MapReduce是一個程式設計模型,也是一個處理和生成超大資料集的演算法模型的相關實現。使用者首先建立一個Map函式處理一個基於key/value pair的資料集合,輸出中間的基於key/val
谷歌三大核心技術(三)Google_BigTable中文版
谷歌三大核心技術(三)Google_BigTable中文版 Bigtable:一個分散式的結構化資料儲存系統 譯者:alex 摘要 Bigtable是一個分散式的結構化資料儲存系統,它被設計用來處理海量資料:通常是分佈在數千臺普通伺服器上的PB
【機器學習】谷歌的速成課程(一)
label spa dev 分類 ram 做出 org ron 表示 問題構建 (Framing) 什麽是(監督式)機器學習?簡單來說,它的定義如下: 機器學習系統通過學習如何組合輸入信息來對從未見過的數據做出有用的預測。 標簽 在簡單線性回歸中,標簽是我們要預測
Hibernate 核心技術(一)
配置 color lac 持久 relation 實體 true obj 輕量級 簡介 Hibernate是一個開源的對象關系映射(ORM)框架。對JDBC進行了非常輕量級的對象封裝。 將對象和數據庫表建立映射關系,Hibernate框架使用在數據持久化層(da
Docker核心技術(一)
Docker核心技術 1.Docker的簡介 1)前提知識和課程定位 2)什麼是Docker 3)Docker能幹什麼? (1)之前的虛擬機器技術 (2)容器虛擬化技術 (3)開發/運維(DevOp
大資料的核心技術(一)
我們在之前的文章中提到過,大資料的核心技術就是機器學習、資料探勘、人工智慧以及其它大資料處理基礎技術。在這篇文章中我們給大家詳細地介紹一下這些內容,希望這篇文章能能夠給大家帶來幫助。 首先說一下機器學習,一般資料分析師都知道,機器學習是大資料處理承上啟下的關鍵技術,機器學習往上是深
Struts2核心技術 (一)
struts2 struts2發展歷史 經過很多年發展,Struts1已經成為了高度成熟的框架,但隨著時間的發展,Struts1的侷限性和缺點不斷的暴露出來。 現在Struts已
Spring的核心技術(一)
這部分參考文件涵蓋了Spring框架中的所有關鍵技術,其中最重要的是Spring框架的控制反轉容器(IoC),然後是與IoC容器緊密結合的Spring的面向切面(AOP)的程式設計技術。Spring框架有它自己的概念上容易理解的AOP框架,它能夠在Java企業及程式設計中滿
谷歌地圖API 學習(一)
google.maps.Marker 1.建立方法 var marker = new google.maps.Marker({ position:pointGGPos,//谷歌地圖經緯
Spring核心技術(一)——IoC容器和Bean簡介
IoC容器和Bean簡介 這章包括了Spring框架對於IoC規則的實現。Ioc也同DI(依賴注入)。而物件是通過建構函式,工廠方法,或者一些Set方法來定義物件之間的依賴的。容器在建立這些Bean物件的時候同時就會注入這些依賴。這個過程是根本上的反轉了,不再
【問底】夏俊:深入站點服務端技術(一)——站點並發的問題
而是 思路 臨時 系統負載 表現 json article 不能 情況 摘要:本文來自擁有十年IT從業經驗、擅長站點架構設計、Web前端技術以及Java企業級開發的夏俊,此文也是《關於大型站點技術演進的思考》系列文章的最新出爐內容。首發於CSDN,各位技術人員不
10.1-全棧Java筆記:最全面的IO技術(一)
javaIO技術對於任何程序設計語言而言,輸入輸出(Input/Output)系統都是非常核心的功能。程序運行需要數據,數據的獲取往往需要跟外部系統進行通信,外部系統可能是文件、數據庫、其他程序、網絡、IO設備等等。外部系統比較復雜多變,那麽我們有必要通過某種手段進行抽象、屏蔽外部的差異,從而實現更加便捷的編
Java加密技術(一)——BASE64與單向加密算法MD5&SHA&MAC
sha256 integer 被人 sent 發現 Coding design 如果 targe http://snowolf.iteye.com/blog/379860 加密解密,曾經是我一個畢業設計的重要組件。在工作了多年以後回想當時那個加密、解密算法,實在是太單
淺談存儲重刪壓縮技術(一)
emc 將他 壓力測試 處理方式 比對 公眾號 center str 今天 淺談重刪壓縮技術(一) <喜歡更多內容可以關註微信公眾號“圍爐煮酒論IT”>作為一個做企業存儲市場的存儲人,最近兩年我不斷被重刪壓縮撩撥著。對於重刪壓縮這個技術的好壞,真實需求還是偽需求
深入理解Flink核心技術(轉載)
優點 流程圖 align 優化器 red 興趣 hdf 定義 lin 作者:李呈祥 Flink項目是大數據處理領域最近冉冉升起的一顆新星,其不同於其他大數據項目的諸多特性吸引了越來越多的人關註Flink項目。本文將深入分析Flink一些關鍵的技術與特性,希望能夠幫助讀者對
asp.net core 擁抱 docker 技術 (一)概覽
測試 docker 架構 swa ima 進程 基於 概念 registry 這是一個huge 坑慢慢填吧。這裏只是一個目錄 或總覽。 docker 是什麽? docker可以看做一種虛擬機技術,但沒有傳統虛擬機那麽復雜,是基於進程的虛擬,就是讓一個一個進程,認為自己處於一
Android Native Hook技術(一)
數組 chef protect 獲取 通過 防止 example tile ofo 原理分析 ADBI是一個著名的安卓平臺hook框架,基於 動態庫註入 與 inline hook 技術實現。該框架主要由2個模塊構成:1)hijack負責將so註入到目標進程空間,2)lib