譯自Bigtable_A Distributed Storage System for Structured Data算法
做者:Fay Chang, Jeffrey Dean, Sanjay Ghemawat, Wilson C.Hsieh, Deborah A. Wallach Mike Burrows, Tushar Chandra, Andrew Fikes, Robert E.Gruber緩存
5 實現服務器
Bigtable包括三個主要組件,分別是連接到客戶端程序的庫、Master服務器以及多個Tablet服務器。Bigtable能夠動態地增刪集羣中的Tablet服務器,調整負載均衡。網絡
Master服務器主要負責如下工做:爲Tablet服務器分配Tablets、檢測新加入的或過時失效的Tablet服務器、調整Tablet服務器的負載均衡以及對GFS上的文件進行垃圾收集。此外,Master服務器還負責處理對模式的相關修改操做,例如建立表和列族。數據結構
每一個Tablet服務器都管理一個Tablet集合(每一個服務器通常有幾十個至上千個Tablet)。每一個Tablet服務器負責處理其所加載的Tablet的讀寫操做,同時負責分割過大的Tablet。負載均衡
和不少Single-Master類型的分佈式存儲系統類似,客戶端讀取的數據都不通過Master服務器,而是經過直接與Tablet服務器通訊進行讀寫操做。所以,大多數客戶端程序徹底不須要和Master服務器通訊,Master服務器的負載很輕。分佈式
一個BigTable集羣存儲了不少表,每一個表包含了一個Tablet集合,而每一個Tablet包含了某個範圍內的行的全部相關數據。在初始狀態下,一個表只有一個Tablet。隨着數據的增加,表被自動分割成多個Tablet,缺省狀況下,每一個Tablet的大小約爲100MB到200MB。性能
5.1 Tablet的位置編碼
咱們經過相似B+樹的三層結構來存儲Tablet的位置信息(圖4)。3d
圖4:Tablet位置層
第一層是存儲在Chubby中的文件,文件包含了RootTablet的位置信息。Root Tablet包含特定元數據表中全部Tablet的位置信息。每一個元數據Tablet包含一個用戶Tablet集合的位置信息。Root Tablet是元數據表的第一個Tablet。RootTablet永遠不會被分割,從而確保Tablet的位置信息存儲結構不會超過三層。
在元數據表中,每一個Tablet的位置信息都存放在一個行關鍵字下面,而這個行關鍵字是由Tablet所在表的標識符和Tablet的最後一行編碼而成的。每一行元數據都存儲了大約1KB的內存數據。在一個大小爲128MB的元數據Tablet 中,採用這種三層結構的存儲模式,能夠標識2^34個Tablet的地址(若是每一個Tablet存儲128MB數據,則總共能夠存儲2^61字節數據)。
客戶端庫會緩存Tablet的位置信息。若是客戶端程序沒有緩存某個Tablet的位置信息,或發現緩存的地址信息不正確,則能夠遞歸的方式在樹狀存儲結構中查詢Tablet的位置信息。若是客戶端緩存是空的,則尋址算法須要經過三次網絡來回通訊尋址,包括一次Chubby讀操做。若是客戶端緩存的地址信息過時了,那麼尋址算法最多可能須要6次來回網絡通訊才能更新數據,由於只有在緩存中查不到數據時才能發現數據過時(假設元數據Tablet不會頻繁移動)。Tablet的地址信息是存放在內存中的,所以對地址信息的操做沒必要訪問GFS文件系統。但咱們通常會預取Tablet地址,從而進一步減小訪問開銷:每當須要從元數據表中讀取一個Tablet的元數據時,都會多讀取幾個Tablet的元數據。
元數據表中還存儲了次要信息,包括每一個Tablet的事件日誌(例如,服務器何時開始爲該Tablet提供服務)。這些信息有助於排查錯誤和性能分析。
5.2 Tablet的分配
一個Tablet只能分配給一個Tablet服務器。Master服務器記錄了當前活躍的Tablet服務器以及Tablet的分配狀況。若是一個Tablet沒有被分配且正好有一個Tablet服務器有足夠的空閒空間裝載該Tablet,Master服務器便會給向Tablet服務器發送裝載請求,將Tablet分配給這個服務器。
Bigtable使用Chubby跟蹤記錄Tablet服務器的狀態。Tablet服務器啓動時會在Chubby的指定目錄下創建一個惟一命名的文件,並獲取該文件的獨佔鎖。Master服務器實時監控該目錄(服務器目錄),及時發現Tablet服務器。若是因爲網絡中斷丟失了Chubby上的獨佔鎖,Tablet服務器便會中止爲Tablet提供服務。(Chubby的高效機制可以確保Tablet服務器在不增長網絡負擔的狀況下知道其是否還持有鎖)。只要文件還存在,Tablet服務器就會試圖從新得到對該文件的獨佔鎖;若是文件不存在了,Tablet服務器就會自行退出,沒法繼續提供服務。Tablet服務器終止時(好比,集羣的管理系統將運行該Tablet服務器的主機從集羣中移除)會嘗試釋放它持有的文件鎖,這樣Master服務器就能儘快把Tablet分配到其它的Tablet服務器。
Master服務器負責檢查Tablet 服務器是否已經中止爲其Tablet提供服務;如是,則儘快從新分配其加載的Tablet。Master服務器經過輪詢Tablet服務器文件鎖的狀態來檢測Tablet服務器什麼時候中止爲Tablet提供服務。若是Tablet服務器報告丟失了文件鎖或Master服務器最近幾回嘗試與其通訊都沒有獲得響應,Master服務器便會嘗試獲取該Tablet服務器文件的獨佔鎖。若是Master服務器成功獲取了獨佔鎖, 則說明Chubby處於正常運行狀態,而Tablet服務器要麼是宕機了、要麼是不能與Chubby通訊了。所以,Master服務器便會刪除該Tablet服務器在Chubby上的服務器文件,確保其再也不給Tablet提供服務。Tablet服務器在Chubby上的服務器文件被刪除後,Master服務器便會把以前分配給該Tablet服務器的全部的Tablet放入未分配的Tablet集合中。爲了確保Bigtable集羣在Master服務器與Chubby之間的網絡出現故障時仍然可使用,Master服務器在其Chubby會話過時後便會主動退出。但Master服務器的故障不會改變現有Tablet在Tablet服務器上的分配狀態。
集羣管理系統啓動Master服務器以後,Master服務器首先要了解當前Tablet的分配狀態,而後纔會修改分配狀態。Master服務器在啓動的時候執行如下步驟:
在元數據Tablet被分配以前,掃描是沒法進行的。所以,在掃描以前(步驟4),若是在第3步的掃描過程當中發現RootTablet尚未分配,Master服務器便會把Root Tablet加入到未分配的Tablet集合,從而確保Root Tablet會被分配。因爲RootTablet包含全部元數據Tablet的名稱,所以當Master服務器掃描完Root Tablet後,就能獲得全部METADATA表的Tablet名稱。
只有出現如下事件時,現有Tablet集合纔會改變:建立新表或刪除舊錶、兩個Tablet被合併、一個Tablet被分割成兩個小的Tablet。Master服務器能夠跟蹤記錄全部這些事件,由於前兩類事件都是由它啓動的。Tablet分割事件須要特殊處理,由於這類事件是由Tablet服務器啓動的。分割操做完成以後,Tablet服務器便會在元數據表中記錄新的Tablet信息,完成提交;提交後,Tablet服務器便會通知Master服務器。若是沒有把分割操做已提交的信息發送給Master服務器(可能Tablet服務器或Master服務器宕機了),Master服務器在要求Tablet服務器裝載已經被分割的子表時便會發現新的Tablet。經過對比元數據表中Tablet信息,Tablet服務器會發現Master服務器要求其裝載的Tablet並不完整,進而從新向Master服務器發送通知信息。
5.3 Tablet服務
如圖5所示,Tablet的持久化狀態信息保存在 GFS 上。更新操做提交到REDO日誌中。在這些更新操做中,最近提交的操做存放在排序的緩存中,咱們稱之爲memtable;較早提交的操做存放在一系列SSTable中。恢復Tablet時,Tablet服務器首先從元數據表中讀取其元數據。元數據包括組成Tablet的SSTable列表以及一系列的Redo標點。這些標點指向可能含有該Tablet數據的已提交日誌記錄。Tablet服務器把SSTable的索引讀進內存,使用在Redo標點以後提交的更新重建memtable。
圖5:Tablet形式
對Tablet服務器進行寫操做時,Tablet服務器首先要檢查該操做格式是否正確、操做發起者是否有執行該操做的權限。權限驗證的方法是從Chubby文件裏讀取有寫權限的操做者列表(這個文件通常存放在Chubby客戶端緩存中)。成功的修改操做會記錄在提交日誌中。能夠經過批量提交的方式提升包含大量小修改操做的應用程序的吞吐量。寫操做提交後,寫的內容便會插入到memtable裏。
對Tablet服務器進行讀操做時,Tablet服務器會進行相似的完整性和權限校驗。有效的讀操做是在由一系列SSTable和memtable合併的視圖裏執行的。SSTable和memtable是按字母順序排序的數據結構,所以能夠高效生成合並視圖。
進行Tablet合併和分割時,正在進行的讀寫操做可以繼續進行。
5.4 壓縮
隨着寫操做的執行,memtable不斷變大。當memtable的大小到達閾值時,該memtable 便會會被凍結,而後建立一個新的memtable;被凍結的memtable會被轉換成SSTable,寫入GFS18。Minor 壓縮過程有兩個目的:一是縮減Tablet服務器使用的內存;而是在服務器災難恢復過程當中,減小必須從提交日誌裏讀取的數據量。在壓縮過程當中,正在進行的讀寫操做仍能繼續進行。
每一次Minor 壓縮都會建立一個新的 SSTable。若是Minor 壓縮過程不間斷地持續進行下去,讀操做可能須要合併來自多個SSTable的更新。爲了限制合併文件的數量,咱們會按期在後臺執行Merging 壓縮過程。Merging 壓縮過程讀取一些SSTable和memtable的內容,合併成一個新的SSTable。Merging壓縮過程完成後,輸入的這些SSTable和memtable就能夠刪除了。
將全部SSTable合併成一個新SSTable的過程叫做Major 壓縮。由非Major 壓縮產生的SSTable可能含有特殊的刪除條目,這些刪除條目收錄了依然有效的原有SSTable中的已刪除數據。而Major 壓縮過程生成的SSTable不包含已經刪除的信息或數據。Bigtable循環掃描全部的Tablet,並按期對Tablet執行Major 壓縮。Major 壓縮機制容許Bigtable回收已刪除數據佔有的資源,而且確保Bigtable能及時清除已刪除的數據,這對存放敏感數據的服務來講很是重要。
參考資料
Fay Chang, Jeffrey Dean, Sanjay Ghemawat, Wilson C.Hsieh, Deborah A. Wallach Mike Burrows, Tushar Chandra, Andrew Fikes and Robert E.Gruber. Bigtable_A Distributed Storage System for Structured Data
Yan Wei. Google Bigtable中文版