小白帶你學習google三篇論文————Google File System

簡述:

  • Google有三劍客,GFS,BigTable以及MapReduce。這三個在一起組成了Google最早期的三篇論文的基礎架構,這篇主要講述gfs.
  • 搜索引擎的支撐架構:

gfs產生的背景

  • 1、 component failures are the norm rather than the exception
    • 組件失效被認為是常態事件,而不是意外事件。(程序 bug、操作系統的 bug、人為失誤,甚至還有硬碟、內存、連接器、網路以及電源失效等造成的問題。所以,持續的監控、錯誤偵測、災難冗餘以及自動恢復的機制必須集成在 GFS 中)

  • 2、Second, files are huge by traditional standards
    • 以通常的標準衡量,文件非常巨大。
  • 3、most files are mutated by appending new data rather than overwriting existing data
    • 絕大部分文件的修改是採用在文件尾部追加數據,而不是覆蓋原有數據的方式 。

  • 4、co-designing the applications and the file system API benefits the overall system by increasing our flexibility
    • 應用程序和文件系統 API 的協同設計提高了整個系統的靈活性。比如:放鬆了對 GFS 一致 性模型的要求,這樣就減輕了文件系統對應用程序的苛刻要求,大大簡化了 GFS 的設計。我們引入了原子性 的記錄追加操作,從而保證多個客戶端能夠同時進行追加操作,不需要額外的同步操作來保證數據的一致性

GFS設計

  • 以問題帶入思考~~~~來嘛
  • 1、怎麼保存一個文件
    • 首先我們有一個硬碟,硬碟需要一些原始信息,比如某個文件叫什麼名字,什麼時候被創建的,大小是多少,這些都是數據。為了尋找這些數據在硬碟中的位置,就需要索引。索引就是這些數據在硬碟上存在的位置,比如Block23,24,25,所以通過這些硬碟上的的偏移量以及每一塊,就可以找到這個文件的所有信息。總結起來,我們這裡所說的「一塊」,在傳統意義上是指1024Byte

  • 2、如何保存大文件

    • 以上我們談到的是小文件,接下來我們看一看如何保存大文件。對於大文件來說,我們不能保存小塊,因為塊數太多了,所以我們只要將每一塊變成大塊,就是64MB,就變成大文件了。
    • 這裡的大塊叫Chunk,相當於6萬多個小塊,這樣可以極大地節省你的空間和原始信息大小。以前一個大塊需要存6萬多個索引的位置,現在只需要存一個了。
    • 這個方案的優點是減少了元數據的大小,也減少了如果以後需要傳遞的話,傳遞的流量信息。但是一個明顯的缺點就是,如果你存了一個小文件,你會浪費空間。比如只存一個1k的小文件,也要浪費一個64MB的大塊
    • 3、如何保存超大文件

    • 問題再變一下,如果要保存一個超大型的文件呢?那我們就不能在1G上存了,因為超大文件往往1個G存不下去。這時我們就需要一個主從結構。Master是保存所有原始信息的地方,這裡會存一個文件,包括它的尺寸,大小,它的索引也可以一樣建立,但它的索引指向的信息是各個Chunk Server,也就是大塊的伺服器,上面有它的偏移量。
    • 所以說,架構其實是一模一樣的,只不過把索引信息放到了大的Master上,將數據分佈到不同機器上,我們只需在偏移量前面記錄機器的偏移量,就可以解決同樣的問題
    • 這相當於是一個Master + many Chunk Servers結構,缺點很明顯:你會發現Chunk Server裏任何的數據變化都要通知Master,因為Master保存了Chunk Server裏的每一個偏移量,這樣就會浪費Master的存儲空間以及相關傳遞的流量。如何解決這個問題呢
    • 4、 如何減少Master存儲的數據和流量

    • 首先,什麼是系統設計中的耦合和聚合。你只要把屬於它的放在它那裡,把不屬於它的發給別人。所以,我們完全可以在Master裏,只保存哪一塊存在哪個伺服器上這一信息,而在每個伺服器上保存它的偏移量。這樣如果本地的數據有任何變化,就只用在本地改索引就行了,而不需要通知Master。當一個塊從一個伺服器變到另外一個伺服器上,才會需要通知Master。因此這會極大地減少Master保存的數據量,索引量和傳遞的數據量。Master根本沒有必要記錄每塊數據的偏移量,這樣的優點就是減少了Master的元數據信息以及Master和Chunk Server之間的通信
    • 5、如何發現數據損壞

    • 現在能保存大文件了,我們再來看一看如何發現一些異常情況,比如數據損壞。首先需要先有一個機制鑒定出數據損壞
    • 現在我們存的每個Block代表的是Chunk裡面的一個小塊,每個小塊可以保存一個小的Checksum,這是什麼意思呢?
    • 現在一個大塊由很多小塊組成,一個小塊可能只有64k,每個小塊還同時保存了一個32bit的Checksum,這是做什麼用的呢?是對這個小塊進行了一個校驗和的演算法,得到32bit的Checksum,可以使用哈希。每次當我讀取的時候,如果把這個block裏的數據再哈希一下,跟這個Checksum裏的不一樣,那這個數據就是錯誤的,如果是一樣的,那這個數據就是正確的。
    • 那這樣會不會佔用很大的空間呢?我們可以計算一下,如果是一個1T的文件,實際上你會發現它只有64MB大小,很容易就可以保存在內存中,進行各種校驗。最終當我讀取一個數據塊的時候,就會對Checksum進行驗證,這樣保證了每次讀取的時候都可以鑒定一下數據是否損壞。

  • 6、如何減少Chunk Server掛掉帶來的損失

    • 假設Chunk3隻存在一個Chunk Server上,那為了減少損失,就需要保存在多個Chunk Server裏,相當於建立副本,副本永遠是分散式系統的基本問題。所以我現在把每個數據塊保存在3個伺服器裏,這樣如果任何一個丟失,我都可以通過其他伺服器進行恢復。所以答案就是創建副本。創建幾個副本呢?答案是3個,原因我們後面會講到。
    • 我們應該如何選擇副本的Chunk Server呢?可以選擇一些硬碟利用率低的Chunk Server,並且儘可能限制數據塊都寫到一個新的硬碟上,也就是限制最新數據塊的寫入數量。比如,你的機房插入了一個新的機器,它有新的硬碟,那他的硬碟利用率必然是很低的。如果按照這個標準,會讓所有數據都寫在這個硬碟上。這樣帶來的問題就是,伺服器裏的數據會聚集起新的數據,因此訪問可能會形成各種熱點,帶來各種問題。所以如果限制一下,讓數據之間平均分佈,可以保證Load balance。
    • 另外一點就是跨機架跨中心:2+1。我們可以把數據放到三個地方, 一個放到加州的數據中心,另外一個放到華盛頓的數據中心,這就叫做跨數據中心。在一個數據中心裡,再放到兩個不同的機架上,就能夠保證不出問題。假如在微信的架構設置裏,不小心將三個副本放到同一個機架裏,如果這個機架掛掉了,就會帶來很大的問題。
    • 7、如何恢復損壞的Chunk

    • 我們剛才已經發現Chunk錯了,現在我有副本了,自然就可以找到其他副本。如果ChunkServer4上的Chunk03壞了,他就可以和Master說:我的Chunk03壞了,誰還有?Master就會告訴他:3和5還有,他可以選擇離它最近的那個,所以他會找Chunk5要。這樣數據就可以恢復了,其中的關鍵點是什麼?就是向Master求助
    • 8、如何發現Chunk Server掛掉了

    • 首先大家都在這裡活著,Master會記錄他們活著的時間,比如5號說我活著,然後他就記錄下活著的時間,3號和2號說我也活著,他也分別記錄了時間,但是4號卻很久不回來,這說明他已經死了,這就是所謂的心跳。如果Chunk Server很長時間內沒有發生心跳的話,並且排除一些故障,就可以判斷他已經死了。
    • 那有的人會問,如果只是Master和Chunk Server之間掛掉怎麼辦呢?也就是說如果只是網路不通怎麼辦呢?其實現在有些新的系統,Master會再找旁邊的幾個兄弟,讓他們再去Pin他一下,比如3和5也去Pin一下4,看他是否活著,這是一種新的心跳方式
    • 9、Chunk Server如果真的掛掉了,怎麼恢複數據呢?

    • 以前我們有很多數據,Chunk Server都記下來了,這時我們發現ChunkServer4掛掉了,於是我們就會在索引裏發現一個紅色,顯示4掛掉了,然後我就會啟動一個修復進程。這個修復進程會記錄擁有少於三個副本的Chunk剩餘的副本數量。比如發現Chunk99剩下一個副本,Chunk03隻有伺服器3和5有,它會記錄下來。
    • 為什麼這樣排序呢?我們可以看到,這是基於存活副本數的恢復策略,如果副本越少,就越應該儘早修復,副本越多,修復得越慢,這樣可以保證我們修復的是最緊急的Chunk Server。

  • 10、如何應對熱點

    • 什麼是熱點?熱點就是某一個數據在短時間裡獲得大量的訪問,就很可能崩潰,造成各種各樣的問題。比如阿里有一萬臺Hadoop系統,經常就會有一些熱點掛死。
    • 那麼Master怎麼應對熱點呢?其實也很簡單,我們只要加一個熱點平衡進程就行,記錄每個數據塊訪問的熱度以及每個伺服器的剩餘空間、帶寬的數量。如果發現一個東西成為熱點時該怎麼辦?把他複製到更多的Chunk Server上就行了,並基於每個伺服器的帶寬和硬碟利用率來進行選擇

  • 11、如何讀文件
    • 到最關鍵的時刻,怎麼讀一個文件?讀和寫往往決定了一個文件系統的核心,所以大家在設計的時候一定要想這兩個問題。前面講了這麼多,我們現在來做一個總結
    • 現在我們有一個Master,上面保存了所有信息,下面有很多Chunk Server。其實頂層的Chunk Server,底層還是利用Linux文件系統來實現的。現在我有一個應用,這個應用為了訪問Master,往往下面需要掛載一個Client,裡麪包含了各種庫函數,以及處理各種連接的問題。他首先會對Master大喊一聲:我要哪個文件。比如他要sum.mp4,並希望它的索引塊是哪一個。
    • 為什麼要傳遞索引塊呢?因為他知道每一塊的大小都是64兆,所以他根據自己訪問的偏移量,可以算出這個索引塊。Master就會在本地的一個文件名空間的樹裡面找到對應原始信息的位置,接著他就會看這個索引塊所在的伺服器是哪一個,找到以後就會告訴他,你現在可以訪問了,也就是Handle,相當於一個訪問的許可權。然後告訴他保存的Location。接著他就拿著Handle找離他最近的伺服器要數據,並且告訴他要讀什麼,讀多少,這樣就可以返回他想要的數據了,這就是一個讀過程,數據最後會返回來

  • 12、如何寫文件?
    • 那寫的過程是怎樣的呢?這個過程非常有意思,因為要寫三份,所以他要處理很多同步的情況。舉個例子,首先我們的應用下面要掛載一個Client,同時他還需要告訴Master他沒地方寫了。他會算出自己要寫哪一塊,並和Master說他要寫某個文件的某一塊,然後Master會告訴他兩個信息,第一個信息是有哪些副本,比如在3,0,5這些伺服器上有副本。第二個信息是哪個Chunk Server是Primary(即臨時設置的負責協調這次寫的主結構),Chunk Server之間本身是沒有什麼優先順序的,只是在這次選這個Chunk Server為主結構。

    • 找到Primary之後,Client就會去找Primary寫東西。有趣的是,大家會發現Client首先連的並不是這個Primary,即ChunkServer3,而是先把數據發給ChunkServer0,為什麼發給ChunkServer0呢?因為他會找離他最近的Server,如果ChunkServer0在中國,而ChunkServer3在美國,那就沒有必要把中國的數據先傳到比較遠的美國的伺服器,可以先傳到中國的伺服器,而中國的伺服器之間有很快的帶寬,所以他們之間會互相聯繫。
    • 也就是說,客戶端會選擇離他最近的伺服器,無論是Primary還是Replica。傳遞過來以後,伺服器之間再通過這種串聯的方式把數據傳遞過去,所以並不是某個伺服器收集到所有數據才開始傳遞,而是隻要收集到數據就開始往後傳,所以能保證傳遞的過程非常快。而且因為後面都是在伺服器之間傳,就會帶來很大的好處。
    • 有時候大家可能會想,Client能不能直接往三個伺服器都發送數據?其實這反而是最爛的過程。同時,這只是一個緩存過程,並不代表任何寫入,所以這個過程只是把數據緩存到三個伺服器上。這樣的好處是什麼?如果你一開始就往硬碟上寫,如果崩潰了怎麼辦?這都是不確定的。而現在緩存上以後,就減少了99%出錯的可能性,最終你在寫的時候,就容易同步,不容易出現各種問題。

    • 寫完以後,5就會告訴3他寫夠了,然後3告訴0他也寫好了,0最後告訴Client都搞定了,大家都緩存好以後,就可以向Primary replica說:大家都緩存好了,你可以開動大家的寫入進程了。這時Primary replica會開始往自己的硬碟上寫,同時通知兩個Replica也開始往自己的硬碟上寫。在寫的過程中,大家寫好以後就會告訴Client他寫好了。

  • 如果中間有一步寫錯了怎麼辦?首先,會有很複雜的機制嗎?不會的。因為作為一個分散式系統,處理錯誤的機制往往會帶來更多的錯誤。所以有錯誤怎麼辦?答案是不管它,告訴客戶端錯了,讓客戶端負責重試。也就是說,底層盡量只是實現基本功能,錯就錯了,不要老想著去修復,修復多了系統會越弄越複雜。簡單事情簡單來,讓Client決定是否重試。

總結

  • GFS是特定於大文件場景的,所以這次了怎麼寫大文件。 在寫文件的過程中,讀寫的是核心。和Linux一樣,Linux文件系統的核心也是「Everything is a file」,即文件的讀寫是核心

推薦閱讀:

相關文章