天天看點

論文學習筆記:BigTable

Bigtable為Google設計的一個分布式結構化資料存儲系統,用來處理Google的海量資料。Google内包括Web索引、Google地球等項目都在使用Bigtable存儲資料。盡管這些應用需求差異很大,但是Bigtable還是提供了一個靈活的、高性能的解決方案。

-----------------------------------------------------------------------------------------------------------------------------------

一、簡介

* 設計目标:可靠的處理PB級别的資料,适用性廣泛、可擴充、高性能和高可用性。

* 很多方面Bigtable和資料庫類似,其也使用了資料庫很多實作政策,但是Bigtable提供了和這些系統完全不同的接口。Bigtable不支援完整的關系資料模型,但為使用者提供了一種簡單的資料模型,使用者可以動态控制資料的分布和格式

二、資料模型

* Bigtable是一個稀疏的、分布式的、持久化存儲的多元排序Map(Key=>Value)。Map的索引(Key)是行關鍵字、列關鍵字和時間戳,Map的值(Value)都是未解析的Byte數組:

    - Key (row:string, col:string, time:int64) => Value (string)

* 下圖是Bigtable存儲網頁資訊的一個例子:

論文學習筆記:BigTable

    - 行:"com.cn.www"為網頁的URL

    - 列:"contents:"為網頁的文檔内容,"anchor:"為網頁的錨連結文本(anchor:為列族,包含2列cnnsi.com和my.look.ca)

    - 時間戳:t3、t5、t6、t8和t9均為時間戳

1、行

* 行和列關鍵字都為字元串類型,目前支援最大64KB,但一般10~100個位元組就足夠了

* 對同一個行關鍵字的讀寫操作都是原子的,這裡類似Mysql的行鎖,鎖粒度并沒有達到列級别

* Bigtable通過行關鍵字的字典序來組織資料,表中每行都可以動态分區。每個分區叫做一個"Tablet",故Tablet是資料分布和負載均衡調整的最小機關。這樣做的好處是讀取行中很少幾列資料的效率很高,而且可以有效的利用資料的位置相關性(局部性原理)

2、列族

* 列關鍵字組成的集合叫做"列族",列族是通路控制的基本機關,存放在同一列族的資料通常都屬于同一類型。

* 一張表列族不能太多(最多幾百個),且很少改變,但列卻可以有無限多

* 列關鍵字的命名文法:列族:限定詞。

* 通路控制、磁盤和記憶體的使用統計都是在列族層面進行的

3、時間戳

* 在Bigtable中,表的每個資料項都可包含同一資料的不同版本,不同版本通過時間戳來索引(64位整型,可精确到毫秒)

* 為了減輕各版本資料的管理負擔,每個列族有2個設定參數,可通過這2個參數可以對廢棄版本資料進行自動垃圾收集,使用者可以指定隻儲存最後n個版本資料

三、API

* 在表操作方面,提供建表、删表、建列族、删列族,以及修改叢集、表和列族中繼資料(如通路權限等)等基本API。一個例子:

論文學習筆記:BigTable

* 在資料操作方面,提供寫入、删除、讀取、周遊等基礎API。一個例子:

論文學習筆記:BigTable

* 根據具體需求,Bigtable還開發出支援一些其他的特性,比如:1 支援單行上的事務處理,2 允許把資料項做整數計數器 3 允許使用者在Bigtable伺服器位址空間上執行腳本程式

四、基礎構件

* Bigtable是建立在其他幾個Google基礎構件上的,有GFS、SSTable、Chubby等

1、基礎存儲相關

* Bigtable使用GFS存儲日志檔案和資料檔案,叢集通常運作在共享機器池(cloud)中,依靠叢集管理系統做任務排程、資源管理和機器監控等

2、資料檔案格式相關

* Bigtable的内部儲存檔案為Google SSTable格式的,SSTable是一個持久化、排序的、不可更改的Map結構

* 從内部看,SSTable是一系列的資料塊,并通過塊索引定位,塊索引在打開SSTable時加載到記憶體中,用于快速查找到指定的資料塊

3、分布式同步相關

* Bigtable還依賴一個高可用的、序列化的分布式鎖服務元件Chubby(類zookeeper)。

* Chubby服務維護5個活動副本,其中一個選為Master并處理請求,并通過Paxos算法來保證副本一緻性。另外Chubby提供一個名字空間,提供對Chubby檔案的一緻性緩存等

* Bigtable使用Chubby來完成幾個任務,比如:1 確定任意時間隻有一個活動Master副本,2 存儲資料的自引導指令位置,3 查找Tablet伺服器資訊等 4 存儲通路控制清單等

五、實作

* Bigtable包括3個主要的元件:連結到使用者程式的庫,1個Master伺服器和多個Tablet伺服器。Tablet伺服器可根據工作負載動态增減

* Master伺服器:為Tablet伺服器配置設定Tablets,對Tablet伺服器進行負載均衡,檢測Tablet伺服器的增減等

* Tablet伺服器:管理一個Tablets集合(十到上千個Tablet),并負責它們的讀寫操作。與一般Single-Master類型的分布式存儲系統類似,用戶端可直接和Tablet伺服器通信并進行讀寫,故Master的負載并不大

* 初始情況下,每個表隻含一個Tablet,随着表資料的增長,它會被自動分割成多個Tablet,使得每個Table一般為100~200MB

1、Tablet的位置資訊

* 我們使用三層的、類B+樹的結構存儲Tablet的位置資訊,如下圖所示:

論文學習筆記:BigTable

* 第一層為存儲于Chubby中的Root Tablet位置資訊。Root Tablet包含一個MetaData表,MetaData表每個Tablet包含一個使用者Tablet集合

* 在MetaData表内,每個Tablet的位置資訊都存儲在一個行關鍵字下,這個行關鍵字由Tablet所在表的辨別符和最後一行編碼而成

* MetaData表每一行都存儲約1KB記憶體資料,即在一個128MB的MetaData表中,采用這種3層存儲結構,可辨別2^32個Tablet位址

* 使用者程式使用的庫會緩存Tablet的位置資訊,如果某個Tablet位置資訊沒有緩存或緩存失效,那麼用戶端會在樹狀存儲結構中遞歸查詢。故通常會通過預取Tablet位址來減少通路開銷

2、Tablet的配置設定

* 在任何時刻,一個Tablet隻能配置設定給一個Tablet伺服器,這個由Master來控制配置設定(一個Tablet沒配置設定,而一個Tablet伺服器用足夠空閑空間,則Master會發給該Tablet伺服器裝載請求)

* Bigtable通過Chubby跟蹤Tablet伺服器的狀态。當Tablet伺服器啟動時,會在Chubby注冊檔案節點并獲得其獨占鎖,當Tablet伺服器失效或關閉時,會釋放這個獨占鎖

* 當Tablet伺服器不提供服務時,Master會通過輪詢Chubby上Tablet伺服器檔案鎖的狀态檢查出來,确認後會删除其在Chubby注冊的節點,使其不再提供服務。最後Master會重新配置設定這個Tablet伺服器上的Tablet到其他未配置設定的Tablet集合内

* 當叢集管理系統啟動一個Master伺服器之後,這個Master會執行以下步驟:

    - 1 從Chubby擷取一個唯一的Master鎖,保證Chubby隻有一個Master執行個體

    - 2 掃描Chubby上的Tablet檔案鎖目錄,擷取目前運作的Tablet伺服器清單

    - 3 和所有Tablet伺服器通信,擷取每個Tablet伺服器上的Tablet配置設定資訊

    - 4 掃描MetaData表擷取所有Tablet集合,如果發現有還沒配置設定的Tablet,就會将其加入未配置設定Tablet集合等待配置設定

3、Tablet的服務

論文學習筆記:BigTable

* 如圖所示,Tablet的持久化狀态資訊儲存在GFS上。更新操作會送出Redo日志,更新操作分2類:

    - 最近送出的更新操作會存放在一個排序緩存中,稱為memtable

    - 較早送出的更新操作會存放在SSTable中,落地在GFS上

* Tablet的恢複:Tablet伺服器從MetaData中讀取這個Tablet的中繼資料,中繼資料裡面就包含了組成這個Tablet的SSTable和RedoPoint,然後通過重複RedoPoint之後的日志記錄來重建(類似Mysql的binlog)

* 對Tablet伺服器寫操作:首先檢查操作格式正确性和權限(從Chubby拉取權限清單)。之後有效的寫記錄會送出日志,也支援批量送出,最後寫入的内容插入memtable内

* 對Tablet伺服器讀操作:也首先檢查格式和權限,之後有效的讀操作在一系列SSTable和memtable合并的視圖内執行(都按字典序排序,可高效生成合并視圖)

4、Compactions

* 當memtable增大達到一個門限值時,這個memtable會轉換為SSTable并建立新的memtable,這個過程稱為Minor Compaction。

* Minor Compaction過程為了減少Tablet伺服器使用的記憶體,以及在災難恢複時減少從送出日志讀取的資料量

* 如果Minor Compaction過程不斷進行下去,SStable數量會過多而影響讀操作合并多個SSTable,是以Bigtable會定期合并SStable檔案來限制其數量,這個過程稱為Major Compaction。

* 除此之外,Major Compaction過程生産的新SStable不會包含已删除的資料,幫助Bigtable來回收已删除的資源

六、優化

1、局部性群族

* 使用者可将多個列族組合成一個局部性群族,Tablet中每個局部性群族都會生産一個SSTable,将通常不會一起通路的分割成不同局部性群族,可以提高讀取操作的效率

* 此外,可以局部性群族為機關專門設定一些調優參數,如是否存儲于記憶體等

2、壓縮

* 使用者可以控制一個局部性群族的SSTable是否壓縮

* 很多使用者使用”兩遍可定制“的壓縮方式:第一遍采用Bentley and Mcllroy(大掃描視窗内常見長字元串壓縮),第二遍采用快速壓縮算法(小掃描視窗内重複資料),這種方式壓縮速度達到100~200MB/s,解壓速度達到400~1000MB/s,空間壓縮比達到10:1

3、緩存

* Tablet伺服器使用二級緩存政策來提高讀操作性能。兩級的緩存針對性不同:

* 第一級緩存為掃描緩存:緩存Tablet伺服器通過SSTable接口擷取的Key-Value對(時間局部性)

* 第二季緩存為塊緩存:緩存從GFS讀取的SSTable塊(空間局部性)

4、布隆過濾器

* 一個讀操作必須讀取構成Tablet狀态的所有SSTable資料,故如果這些SSTable不在記憶體便需多次通路磁盤

* 我們允許使用者使用一個Bloom過濾器來查詢SStable是否包含指定的行和列資料,付出少量Bloom過濾器記憶體存儲代價,換來顯著減少通路磁盤次數

5、Commit日志實作

* 如果每個Tablet操作的Commit日志單獨寫一個檔案,會導緻日志檔案數過多,寫入GFS會産生大量的磁盤Seek操作而産生負面影響

* 優化:設定為每個Tablet伺服器寫一個公共的日志檔案,裡面混合了各個Tablet的修改日志。

* 這個優化顯著提高普通操作性能,卻讓恢複工作複雜化。當一台Tablet伺服器挂了,需要将其上面的tablet均勻恢複到其他Tablet伺服器,則其他伺服器都得讀取完整的Commit日志。為了避免多次讀Commit日志,我們将日志按關鍵字排序(table, row, log_seq),讓同一個Tablet的記錄檔連續存放

6、Tablet恢複提速

* Master轉移Tablet時,源Tablet伺服器會對這個Tablet做一次Minor Compaction,減少Tablet伺服器日志檔案沒有歸并的記錄,進而減少了恢複時間

7、利用不變性

* 在使用Bigtable時,除了SSTable緩存外其他部分産生的SSTable都是不變的,可以利用這個不變性對系統簡化

七、性能評估

* 實驗設計:N台Tablet伺服器叢集(N=1、50、250、500...),每台Tablet伺服器1G記憶體,資料寫入一個含1786台機器的GFS叢集。使用N台Client産生工作負載,這些機器都連入一個兩層樹狀網絡,根節點帶寬約100~200Gbps。

* 一共有6組基準測試:序列寫、随機寫、序列讀、随機讀、随機讀(記憶體)和掃描,測試結果如下圖所示:

論文學習筆記:BigTable

測試均為讀/寫1000位元組value的資料,圖1顯示了1/50/250/500台Tablet伺服器,每台伺服器的每秒操作次數,圖2曲線顯示随着Tablet伺服器數量增加,所有伺服器的每秒操作次數總和

* 對于圖1單個Tablet伺服器性能次元,有下面幾個特點:

    - 随機讀性能最慢,這是因為每個随機讀操作都要通過網絡從GFS叢集拉回64KB(1塊)資料到Tablet伺服器

    - 随機讀(記憶體)性能很快,因為這些讀操作的資料都從Tablet伺服器的記憶體讀取

    - 序列讀性能好于随機讀,因為每次從GFS取出64KB資料,這些資料會緩存,序列讀很多落到同個塊上而減少GFS讀取次數

    - 寫操作比讀操作高,因為寫操作實質上為Tablet伺服器直接把寫入内容追加到Commit日志檔案尾部(随機寫和序列寫性能相近的原因),最後再采用批量送出的方式寫入GFS

    - 掃描的性能最高,因為Client的每一次RPC調用都會傳回大量value資料,抵消了RPC調用消耗

* 對于圖2Tablet伺服器叢集性能次元,有下面幾個特點:

    - 随着Tablet伺服器的增加,系統整體吞吐量有了夢幻般的增加,之是以會有這樣的性能提升,主要是因為基準測試的瓶頸是單台Tablet伺服器的CPU

    - 盡管如此,性能的增加也不是線性的,這是由于多台Tablet伺服器間負載不均衡造成的

    - 随機讀的性能提升最小,還是由于每個1000位元組value的讀操作都會導緻一個64KB塊的網絡傳輸,消耗了網絡的共享帶寬

八、實際應用

* 截止到2006年,Google内部一共運作了388個非測試的Bigtable叢集,約24500台Tablet伺服器,這些應用以及應用資料大緻如下:

論文學習筆記:BigTable

* 如上圖所示,可以了解到Google分析,Google地圖,Google個性化查詢等應用的Bigtable使用情況

九、經驗教訓

* 很多類型的錯誤都會導緻大型分布式系統受損,而不僅僅是網絡中斷等“正常”錯誤。我們使用修改協定來解決這些問題(容錯性),如在RPC機制中加入Checksum等

* 需要在徹底了解一個新特性如何使用後,再決定添加這個新特性是否是重要的。

* 系統級的監控對Bigtable非常重要,能有效跟蹤叢集狀态、檢查引發叢集高時延的潛在因素等

* 簡單的設計和編碼給維護和調試帶來了巨大的好處

繼續閱讀