Google Bigtable (中文版)

http://dblab.xmu.edu.cn/post/google-bigtable/php

Abstracthtml

        BigTable是一個分佈式存儲系統,它能夠支持擴展到很大尺寸的數據:PB級別的數據,包含幾千個商業服務器。Google的許多項目都存儲在BigTable中,包括WEB索引、Google Earth 和Google Finance。這些應用對BigTable提出了大相徑庭的需求,不管是從數據量(從URL到網頁到衛星圖像)而言,仍是從延遲需求(從後端批量處理到實時數據服務)而言。儘管這些不一樣的需求,BigTable已經爲全部的Google產品提供了一個靈活的、高性能的解決方案。本文中,咱們描述了BigTable提供的簡單數據模型,它容許客戶端對數據部署和格式進行動態控制,咱們描述了BigTable的設計和實施。web

中文關鍵詞:谷歌;分佈式存儲系統;鍵值存儲;數據庫;雲數據庫;正則表達式

英文關鍵詞:Google Bigtable;key-value store; database; cloud database;distributed storage system算法

1 Introduction數據庫

        在過去的兩年半時間裏,咱們已經設計、實施和部署了一個分佈式存儲系統BigTable,來管理Google當中的結構化數據。BigTable被設計成能夠擴展到PB的數據和上千個機器。BigTable已經達到了幾個目標:普遍應用性、可擴展性、高性能和高可用性。Google的六十多款產品和項目都存儲在BigTable中,包括Google Analytics和Google Finance,Orkut,Personalized Search,Writely和Google Earth。這些產品使用BigTable來處理不一樣類型的工做負載,包括面向吞吐量的批處理做業以及對延遲敏感的終端用戶數據服務。這些產品所使用的BigTable的簇,涵蓋了多種配置,從幾個到幾千個服務器,而且存儲了幾百TB的數據。express

        在許多方面,BigTable都和數據庫很類似,它具備和數據庫相同的實施策略。並行數據庫[14]和內存數據庫[13]已經取得了可擴展性和高性能,可是BigTable提供了和這些系統不同的接口。BigTable不能支持完整的關係型數據模型,相反,它爲客戶提供了一個簡單數據模型,該數據模型能夠支持針對數據部署和格式的動態控制,而且能夠容許用戶去推理底層存儲所展示的數據的位置屬性。BigTable使用行和列名稱對數據進行索引,這些名稱能夠是任意字符串。BigTable把數據視爲未經解釋的字符串,雖然,客戶可能常常把不一樣格式的結構化數據和非結構化數據都序列化成字符串。最後,BigTable模式參數容許用戶動態地控制,是從磁盤得到數據仍是從內存得到數據。bootstrap

        本文第2部分詳細描述了數據模型,第3部分大概介紹了用戶API,第4部分簡要介紹了BigTable所依賴的Google底層基礎設施,第5部分描述了BigTable的實施方法,第6部分描述了咱們針對BigTable作的性能改進,第7部分提供了BigTable的性能衡量方法,第8部分給出了幾個實例來介紹 Google如何使用BigTable,第9部分介紹了咱們在設計和支持BigTable過程當中獲得的經驗教訓。最後,在第10部分介紹相關工做,第11部分給出結論。後端

2 Data Model數組

        一個BigTable是一個稀疏的、分佈的、永久的多維排序圖。咱們採用行鍵盤(row key)、列鍵(column key)和時間戳(timestamp)對圖進行索引。圖中的每一個值都是未經解釋的字節數組。

(row:string, column string, time:int64)→string

        咱們在檢查了相似BigTable的系統的多種應用之後,才決定採用這種數據模型。這裏給出一個實際的例子來闡釋爲何咱們採用數據模型設計。假設咱們想要拷貝一個可能被不少項目都是用的、很大的網頁集合以及相關的信息,讓咱們把這個特定的表稱爲Webtable。在Webtable當中,咱們使用URL做爲行鍵,網頁的不一樣方面做爲列鍵,並把網頁的內容存儲在contents:column中,如圖1所示。

Google Bigtable,廈門大學,廈門大學計算機系,數據庫實驗室,林子雨

1 存儲了網頁數據的Webtable的一個片斷。行名稱是反轉的URL,contents列家族包含了網頁內容,anchor列家族包含了任何引用這個頁面的anchor文本。CNN的主頁被Sports Illustrated和MY-look主頁同時引用,所以,咱們的行包含了名稱爲」anchor:cnnsi.com」和」anchor:my.look.ca」的列。每一個anchor單元格都只有一個版本,contents列有三個版本,分別對應於時間戳t3,t5和t6。

Rows

        一個表中的行鍵,是任意的字符串(當前在尺寸上有64KB,雖然10-100字節是用戶最經常使用的尺寸)。對每一個行鍵下所包含的數據的讀或寫都是一個原子操做,無論這個行中所包含的列的數量是多少。這種設計決定可使得當針對同一行發生併發更新行爲時,用戶很容易知道系統的行爲。

        BigTable在行鍵上根據字典順序對數據進行維護。對於一個表而言,行區間是動態劃分的。每一個行區間稱爲一個Tablet,它是負載均衡和數據分發的基本單位。於是,讀取一個比較短的行區間是很是高效的,通暢只須要和少數幾個機器通信。用戶能夠利用這種屬性,也就是說,用戶能夠選擇分佈具備局部性的行區間。例如,在Webtable中,經過對URL地址進行反轉,屬於同一個領域的網頁都會被分組到連續的行中。例如,咱們在鍵com.google.maps/index.html下面存儲com.google.maps/index.html中包含的數據。把來自同一個領域的數據彼此臨近存儲,使得一些領域分析更加高效。

Column Families

        列鍵被分組成稱爲「列家族」的集合,它成爲基本的訪問控制單元。存儲在一個列家族當中的全部數據,一般都屬於同一個數據類型(咱們對同一個列家族中的數據一塊兒進行壓縮)。數據能夠被存放到列家族的某個列鍵下面,可是,在把數據存放到這個列家族的某個列鍵下面以前,必須首先建立這個列家族。在建立完成一個列家族之後,就可使用同一個家族當中的列鍵。咱們的意願是,讓一個表當中所包含的列家族的數量儘量少(至多幾百個列家族),並且,在操做過程中,列家族不多發生變化。相反,一個表能夠包含無限數量的列。

        列鍵採用下面的語法命名:family:qualifier。列家族名字必須是可打印的,可是,修飾符qualifier能夠是任意字符串。好比,對於Webtable而言,有一個列家族是language,它存儲了網頁所用語言的信息。在language列家族中,咱們只使用一個列鍵,它存儲了每一個網頁語言的ID。Webtable當中另外一個有用的列家族就是anchor,這個列家族中的每一個列鍵都表明了一個單個的anchor,如圖1所示。它的修飾符qualifier是引用網站的名稱,這個單元格內容是連接文本。

        訪問控制以及磁盤和內存審計是在列家族層面上進行的。以Webtable爲例,這些控制容許咱們管理幾種不一樣類型的應用,一些應用負責增長新的基本數據,一些應用負責讀取基本數據而且建立衍生的列家族,一些應用則只被容許瀏覽現有的數據(甚至,若是出於隱私保護考慮,沒法瀏覽所有列家族)。

Timestamps

        在BigTable中的每一個單元格當中,都包含相同數據的多個版本,這些版本採用時間戳進行索引。BitTable時間戳是64位整數。BigTable對時間戳進行分配,時間戳表明了真實時間,以微秒來計算。客戶應用也能夠直接分配時間戳。須要避免衝突的應用必須生成惟一的時間戳。一個單元格的不一樣版本是根據時間戳降序的順序進行存儲的,這樣,最新的版本能夠被最早讀取。

        爲了減輕版本數據的管理負擔,咱們支持兩種「每列家族」設置,它會告訴BigTable來自動垃圾收集(garbage-collect)單元格版本。用戶能夠設定只保存單元格中數據的最近n個版本,或者只保存足夠新版本(好比只保存最近7天內的數據版本)。

        在咱們的Webtable實例當中,咱們爲存儲在contents:column中的網頁設置時間戳,時間戳的數值就是這個網頁的這個版本被抓取的真實時間。上面所描述的垃圾收集機制,容許咱們只保留每一個網頁的最近三個版本。

3 API

        BigTable的API提供了刪除和建立表和列家族的功能。它還提供了改變簇、表和列家族的元數據,好比訪問控制權限。

        客戶應用能夠書寫和刪除BigTable中的值,從單個行中查詢值,或者對錶中某個數據子集進行遍歷。圖2顯示了一段C++代碼,它使用了RowMutation來執行一系列的更新(爲了更好地理解這個例子,已經忽略了不相關的細節)。對Apply的調用,會執行一個針對Webtable的原子更新操做:它增長一個anchor到www.cnn.com中去,而且刪除一個不一樣的anchor。

// Open the tableTable *T = OpenOrDie(「/bigtable/web/webtable」);// Write a new anchor and delete an old anchorRowMutation r1(T, 「com.cnn.www」);r1.Set(「anchor:www.c-span.org」, 「CNN」);r1.Delete(「anchor:www.abc.com」);

 

Operation op;

Apply(&op, &r1);

圖2: Writing to Bigtable.

        圖3顯示了一段C++代碼,它使用了Scanner來遍歷某個行中的全部anchor(廈門大學林子雨標註:中文能夠翻譯成「錨」)。客戶端能夠遍歷多個列家族,而且有幾種機制能夠用來對一次掃描中所產生的行、列和時間戳的數量進行限制。例如,咱們能夠對上面的掃描進行限制,讓所產生的anchor所在的列與正則表達式匹配anchor:*.cnn.com,或者只產生那些時間戳距離當前時間10天之內的anchor。

Scanner scanner(T);

ScanStream *stream;

stream = scanner.FetchColumnFamily(「anchor」);

stream->SetReturnAllVersions();

scanner.Lookup(「com.cnn.www」);

for (; !stream->Done(); stream->Next()) {

printf(「%s %s %lld %sn」,

scanner.RowName(),

stream->ColumnName(),

stream->MicroTimestamp(),

stream->Value());

}

圖3: Reading from Bigtable.

        BigTable支持幾種其餘的功能,容許用戶以更加複雜的方式來操做數據。首先,BigTable支持單行事務,能夠容許對存儲在某個行鍵下面的數據執行原子的「讀-修改-寫」操做。BigTable當前不支持通用的跨行鍵的事務,雖然它在客戶端提供了跨行鍵批量寫入數據的接口。其次,BigTable容許單元格被用來做爲整數計數器。最後,BigTable支持在服務器的地址空間內執行客戶端提供的腳本。這種腳本是用稱爲Sawzall的語言開發的,這種語言是Google開發出來進行數據處理的。目前,基於Sawzall的API不容許客戶端腳本對BigTable執行回寫操做,可是,它確實容許不一樣類型的數據轉換、基於任意表達式的過濾以及針對不一樣類型操做符的總結。

        BigTable能夠和MapReduce[12]一塊兒使用,MapReduce是Google開發的、用來運行大規模並行計算的框架。咱們已經書寫了一個Wrapper集合,它容許BigTable被用來做爲一個MapReduce做業的輸入源或者輸出目標。

 

4 Building Blocks

        BigTable是構建在其餘幾個Google基礎設施之上的。BigTable使用了分佈式Google文件系統(GFS[17])來存儲日誌和數據文件。BigTable的一個簇一般在一個共享機器池內進行操做,這個共享機器池會運行其餘一些分佈式應用。BigTable的進程一般和其餘應用的進程共享一樣的機器。BigTable依賴一個簇管理系統來調度做業、在共享機器上調度資源、處理機器失敗和監督機器狀態。

        Google SSTable文件格式做爲存儲BigTable數據的內部格式。一個SSTable提供一個持久化的、排序的、不可變的、從鍵到值的映射,其中,鍵和值都是任意的字節字符串。BigTable提供了查詢與一個指定鍵相關的值的操做,以及在一個指定的鍵區間內遍歷全部的「鍵/值對」的操做。在內部,每一個SSTable都包含一個塊序列。一般,每一個塊是64KB,不過塊尺寸是可配置的。存儲在SSTable結尾的塊索引,能夠用來快速定位塊的位置。當SSTable被打開時,塊索引就會被讀入內存。一個查詢操做只須要進行一次磁盤掃描,咱們首先在內存的塊索引當中使用二分查找方法找到合適的塊,而後從磁盤中讀取相應的塊。可選地,一個SSTable能夠被徹底讀入內存,這樣,咱們在進行查找操做時,就不須要讀取磁盤。

        BigTable依賴一個高可用的、持久性的分佈式鎖服務Chubby[8]。一個Chubby服務包含5個動態副本,其中一個被選做主副本對外提供服務。當大部分副本處於運行狀態而且可以彼此通訊時,這個服務就是可用的。Chubby使用Paxos算法[9][23]來使它的副本在失敗時保持一致性。Chubby提供了一個名字空間,它包含了目錄和小文件。每一個目錄和文件能夠被用做一個鎖,針對文件的讀和寫操做都是原子的。Chubby客戶端函數庫提供了針對Chubby文件的持久性緩存。每一個Chubby客戶端維護一個session,這個session具有Chubby服務。若是租約過時之後不能及時更新session的租約,那麼這個客戶端的session就會過時。當一個客戶端的session過時時,它會丟失全部鎖,而且放棄句柄。Chubby客戶端也能夠註冊針對Chubby文件和目錄的回調服務(callback),從而通知session過時或其餘變化。

        BigTable使用Chubby來完成許多任務:(1)保證在每一個時間點只有一個主副本是活躍的,(2)來存儲BigTable數據的bootstrap的位置(見5.1節),(3)來發現tablet服務器,(4)宣告tablet服務器死亡,(5)存儲BigTable模式信息(即每一個表的列家族信息),以及(6)存儲訪問控制列表。若是在一段時間之後,Chubby變得不可用,BigTable就不可用了。咱們最近對涵蓋11個Chubby實例的14個BigTable簇進行了這方面的效果測試。因爲Chubby的不可用(可能因爲Chubby過期,或者網絡故障),而致使一些存儲在BigTable中的數據變得不可用,這種情形佔到BigTable服務小時的平均比例值是0.0047%。單個簇的百分比是0.0326%。

5 Implementation

        BigTable實現包括三個主要的功能組件:(1)庫函數:連接到每一個客戶端,(2)一個主服務器,(3)許多Tablet服務器。Tablet服務器能夠根據工做負載的變化,從一個簇中動態地增長或刪除。主服務器負責把Tablet分配到Tablet服務器,探測Tablet服務器的增長和過時,進行Table服務器的負載均衡,以及GFS文件系統中的垃圾收集。除此之外,它還處理模式變化,好比表和列家族建立。

        每一個Tablet服務器管理一個Tablet集合,一般,在每一個Tablet服務器上,咱們會放置10到1000個Tablet。Tablet服務器處理針對那些已經加載的Tablet而提出的讀寫請求,而且會對過大的Tablet進行劃分。

        就像許多單服務器分佈式存儲系統同樣[17,21],客戶端並非直接從主服務器讀取數據,而是直接從Tablet服務器上讀取數據。由於BigTable客戶端並不依賴於主服務器來得到Tablet的位置信息,因此,大多數客戶端歷來不和主服務器通訊。從而使得在實際應用中,主服務器負載很小。

        一個BigTable簇存儲了許多表。每一個表都是一個Tablet集合,每一個Tablet包含了位於某個域區間內的全部數據。在最初階段,每一個表只包含一個Tablet。隨着表的增加,它會被自動分解成許多Tablet,每一個Tablet默認尺寸大約是100到200MB。

5.1 Tablet Location

咱們使用了一個相似於 B+樹的三層架構(如圖4所示),來存儲Tablet位置信息。

Google Bigtable,廈門大學,廈門大學計算機系,數據庫實驗室,林子雨

第一個層次是一個文件,存儲在Chubby中,它包含了Toot Tablet的位置信息。Root Tablet把Tablet的全部位置信息都保存在一個特定的METADATA表中。每一個METADATA表都包含了一個user tablet集合的位置信息。Root Tablet其實就是METADATA表當中的第一個Tablet,可是,它被區別對待,它在任何狀況下都不會被拆分,從而保證Tablet位置層次結構不會超過三層。

METADATA表存儲了屬於某個行鍵的Tablet的位置信息,所謂行鍵,就是關於Tablet表標識符和它的最後一行這兩者的編碼。每一個METADATA行,大約在內存中存儲了1KB的數據。因爲採用了128M大小的METADATA Tablet的適當限制,咱們的三層位置模式足夠用來存放2的34此方的Tablet的位置信息。

客戶端函數庫會緩存Tablet位置信息。若是客戶端不知道一個Tablet的位置信息,或者它發現,它所緩存的Tablet位置信息部正確,那麼,它就會在Tablet位置層次結構中依次向上尋找。若是客戶端緩存是空的,那麼定位算法就須要進行三次輪詢,其中就包括一次從Chubby中讀取信息。若是客戶端的緩存是過時的,定位算法就要進行六次輪詢,由於,只有在訪問無效的時候纔會發現緩存中某個entry是過時的(這裏假設METADATA Tablets不會頻繁移動)。雖然,Tablets位置信息是保存在緩存中,從而不須要訪問GFS,可是,咱們仍然經過讓客戶端庫函數預抓取tablet位置信息,來進一步減小代價,具體方法是:每次讀取METADATA表時,都要讀取至少兩條以上的Tablet位置信息。

咱們也在METADATA表中存儲了二級信息,包括一個日誌,它記載了和每一個tablet有關的全部事件,好比,一個服務器何時開始提供這個tablet服務。這些信息對於性能分析和程序調試是很是有用的。

5.2 Tablet Assignment

        在每回,每一個Tablet能夠被分配到一個tablet服務器。主服務器跟蹤tablet服務器的狀況,掌握當前tablet被分配到tablet服務器的狀況,其中包括哪一個tablet尚未被分配。當一個tablet沒有被分配,而且一個具備足夠空間能夠容納該tablet的tablet服務器是可用時,主服務器就把當前這個tablet分配給這個tablet服務器,主服務器會向tablet服務器發送一個tablet負載請求。

        BigTable使用Chubby來跟蹤tablet服務器。當一個Tablet服務器啓動的時候,它建立而且得到一個獨佔的排他鎖,這個鎖會鎖住一個特定的Chubby目錄中的一個惟一命名的文件。主服務器監視這個目錄(服務器目錄),來發現tablet服務器。若是一個tablet服務器中止服務,它就會丟失這個鎖,好比,因爲網絡故障,致使這個tablet服務器丟失了這個Chubby會話。(Chubby提供了一個完善的機制,來容許一個tablet服務器檢查本身是否已經丟失了這個獨佔排他鎖)。若是丟失了鎖,那麼,只要目錄中的這個文件還存在,那麼一個tablet服務器就會努力去得到這個鎖。若是文件再也不存在,那麼,這個tablet服務器就再也不可以對外提供服務,所以,它就自殺。一旦一個tablet服務器終止了服務(好比,簇管理系統把這個tablet服務器從簇中移除),它就會努力釋放鎖,這樣,主服務器就能夠更快地從新分配這個tablet。

        主服務器須要探測,何時tablet服務器再也不提供tablet服務,而且要負責儘快對這些tablet進行從新分配。爲了探測何時tablet服務器再也不提供tablet服務,主服務器會週期性地詢問每一個tablet服務器,瞭解他們的鎖的狀態。若是一個tablet服務器報告,它已經丟失了鎖;或者,在最近的幾回嘗試中,主服務器都沒法與tablet服務器取得聯繫,主服務器就會努力得到一個針對這個服務器文件的獨佔排他鎖。若是主服務器能夠得到這個鎖,那麼,Chubby就是可用的,相應地,這個tablet服務器或者已經死亡,或者有些故障致使它沒法到達Chubby。所以,主服務器就從Chubby中刪除這個tablet服務器的文件,從而確保這個tablet服務器再也不可以提供服務。一旦一個服務器文件被刪除,主服務器就能夠把全部之前分配給該服務器的tablet,都移動到「待分配」tablet集合。爲了保證一個BigTable簇不會輕易受到主服務器和Chubby之間的網絡故障的影響,若是一個主服務器的Chubby會話過時了,這個主服務器就會自殺。可是,正如上所述,主服務器失效,不會改變tablet到table的分配。

        當一個主服務器被簇管理系統啓動時,在它可以改變tablet分配以前,它必須首先了解當前的tablet分配信息。爲此,在啓動的時候,主服務器會執行如下步驟:(1)主服務器在Chubby中抓取一個獨特的master lock,這就防止了多個主服務器併發啓動的情形。(2)主服務器掃描Chubby中的服務器目錄,從而發現當前可用的服務器。(3)主服務器和當前每一個可用的tablet服務器通訊,來發現哪些tablets已經被分配到哪一個tablet服務器。(4)主服務器掃描METADATA表來學習tablets表集合。一旦在掃描過程當中,主服務器發現某個tablet尚未被分配,主服務器就把這個tablet放置到「待分配」tablet集合,這就使得這些tablet能夠進入待分配狀態。

        一個比較複雜的狀況是,在METADATA tablets被分配以前,咱們是不能掃描METADATA表的。所以,在開始掃描(步驟4)以前,若是主服務器在步驟3的掃描中發現root tablet沒有被發現,主服務器把root tablet增長到待分配tablet集合。這個增長,保證了root tablet必定會被分配。由於,root tablet包含了全部METADATA tablets的名字。主服務器只有在掃描了root tablet之後,纔可能知道全部這些METADATA tablets的名字。

        現有的tablet集合,只有在如下情形纔會發生改變:(1)當一個tablet被建立或刪除;(2)對兩個現有的tablet進行合併獲得一個更大的tablet;(3)一個現有的tablet被分割成兩個較小的tablet。主服務器能夠跟蹤這些變化。Tablet分裂會被特殊對待,由於,它是由一個tablet服務器發起的。Tablet服務器經過把信的tablet信息記錄在METADATA表中,來提交分裂操做。當分裂被提交之後,這個tablet服務器會通知主服務器。爲了防止分裂通知丟失(或者因爲主服務器死亡或者因爲tablet服務器死亡),當主服務器要求一個tablet服務器加載已經被分裂的tablet時,主服務器會對這個新的tablet進行探測。Tablet服務器會把分裂的狀況告知主服務器,由於,它在METADATA表中所找到的tablet entry,只能肯定主服務器要求它加載的數據的一部分。

5.3 Tablet Serving

Google Bigtable,廈門大學,廈門大學計算機系,數據庫實驗室,林子雨

一個tablet的持久化存儲是存在GFS當中,如圖5所示。更新被提交到一個提交日誌,日誌中記錄了redo記錄。在這些更新當中,最近提交的更新被存放到內存當中的一個被稱爲memtable的排序緩衝區,比較老的更新被存儲在一系列SSTable中。爲了恢復一個tablet,tablet服務器從METADATA表當中讀取這個tablet的元數據。這個元數據包含了SSTable列表,其中,每一個SSTable都包括一個tablet和一個重作點(redo point)的集合,這些redo point是一些指針,它們指向那些可能包含tablet所需數據的重作日誌。服務器把SSTable索引讀入內存,而且重構memtable,方法是,執行重作點之後的全部已經提交的更新。

當一個寫操做到達tablet服務器,服務器首先檢查它是不是良好定義的,而且發送者是否被受權執行該操做。執行受權檢查時,會從一個Chubby文件中讀取具備訪問權限的寫入者的列表,這個Chubby文件一般總可以在Chubby客戶端緩存中找到。一個有效的變化,會被寫到提交日誌中。分組提交是爲了改進許多小更新[13,16]操做的吞吐量。在寫操做已經被提交之後,它的內容就會被插入到memtable。

當一個讀操做到達Tablet服務器,與寫操做相似,服務器也會首先檢查它是不是良好定義和獲得受權的。一個有效地讀操做是在如下兩者的合併的基礎上執行的,即一系列SSTable和memtable。因爲SSTable和memtable是字典排序的數據結構,合併視圖的執行是很是高效的。

當tablet發生合併或分解操做時,正在到達的讀寫操做仍然能夠繼續進行。

5.4 Compactions

        隨着寫操做的執行,memtable的尺寸逐漸增長。當memtable的尺寸到達一個門檻值的時候,memtable就被凍結,就建立一個新的memtable,被凍結的memtable就轉化成一個SSTable,並被寫入到GFS。這個「次壓縮」(minor compaction)過程有兩個目標:(1)它縮減了tablet服務器的內存使用率;(2)當發生服務器死亡須要恢復時,它減小了須要從重作日誌中讀取的數據量。當壓縮過程正在進行時,正在到達的讀寫操做仍然能夠繼續進行。

        每一次小壓縮都會建立一個新的SSTable,若是這種行爲沒有限制地持續進行,讀操做可能須要從任意數量的SSTable中合併更新。相反,咱們會對這種文件的數量進行限制,咱們在後臺週期性地運行一個合併壓縮程序。一個合併壓縮程序從一些SSTable和memtable中讀取內容,而且寫出一個新的SSTable。一旦壓縮過程完成,這個輸入的SSTable和memtable就能夠被刪除。

        一個合併壓縮程序,把全部的SSTable的數據重寫到一個SSTable,這個合併壓縮被稱爲「主壓縮」(major compaction)。非主壓縮所產生的SSTable能夠包含特殊的刪除入口(entry),它把被刪除的數據壓縮在仍然存活的比較老的SSTable當中。另外一方面,一個主壓縮過程,產生一個SSTable,它不包含刪除信息或被刪除的數據。BigTable按期檢查它的全部tablet,並執行主壓縮操做。這些主壓縮過程能夠容許BigTable收回被刪除數據佔用的資源,而且保證被刪除數據在必定時間內就能夠從系統中消失,這對於一些存儲敏感數據的服務來講是很是重要的。

6 Refinements

   之前章節所描述的實現,須要一系列完善措施從而得到高性能、可用性和可靠性,這些都是咱們的用戶所要求的。這部份內容更詳細介紹實現細節。

Locatity groups

        客戶端能夠把多個列家族一塊兒分組到一個locality group中。咱們會爲每一個tablet中的每一個locality group大都建立一個單獨的SSTable。把那些一般不被一塊兒訪問的列家族分割到不一樣的locality group,能夠實現更高效的讀。例如,在WebTable當中的頁元數據(好比語言和校驗碼),能夠被放置到同一個locality group當中,網頁的內容能夠被放置到另外一個locality group當中。那些想要讀取頁面元數據的應用,就不須要訪問全部的頁面內容。

        除此之外,一些有用的參數,能夠針對每一個locality group來設定。例如,一個locality group能夠設置成存放在內存中。常駐內存的locality group的SSTable,採用被動加載的方式被加載tablet服務器的內存,即只有應用請求SSTable中的數據,而這些數據又不在內存中時,才把SSTable加載到內存。一旦加載,屬於這些locality group的列家族,就能夠被應用直接訪問,而不須要讀取磁盤。這個特性對於那些被頻繁訪問的小量數據來講是很是有用的。

Compression

客戶端能夠決定是否對相應於某個locality group的SSTable進行壓縮,若是壓縮,應該採用什麼格式。用戶自定義的壓縮格式能夠被應用到每一個SSTable塊中(塊的尺寸能夠採用與locality group相關的參數來進行控制)。雖然對每一個塊進行單獨壓縮會損失一些空間,可是,咱們能夠從另外一個方面受益,當解壓縮時,只須要對小部分數據進行解壓,而不須要解壓所有數據。許多客戶端都使用「兩段自定義壓縮模式」。第一遍使用Bentley and McIlroy[6]模式,它對一個大窗口內的長公共字符串進行壓縮。第二遍使用一個快速的壓縮算法,這個壓縮算法在一個16KB數據量的窗口內尋找重複數據。兩個壓縮步驟都很是快,在現代計算機上運行,他們編碼的速度是100-200MB/S,解碼的速度在400-1000MB/S。

當選擇咱們的壓縮算法時,即便咱們強調速度而不是空間壓縮率,這個兩段壓縮模式也表現出了驚人的性能。例如,在WebTable中,咱們使用這種壓縮模式來存儲網頁內容。在其中一個實驗當中,咱們在一個壓縮後的locality group當中存儲了大量的文檔。爲了達到實驗的目的,咱們只爲每一個文檔存儲一個版本,而不是存儲咱們能夠得到的全部版本。這個壓縮模式得到了10:1的空間壓縮率。這比傳統的GZip方法的效果要好得多,GZip針對HTML數據一般只能得到3:1到4:1的空間壓縮率。這種性能上的改進,是和WebTable中的行的存儲方式緊密相關的,即全部來自同一個站點的網頁都存儲在相近的位置。這就使得Bentley and McIlroy算法能夠從同一個站點的網頁中肯定大量類似的內容。許多應用,不僅是WebTable,都會很好地選擇行名稱,從而保證類似的數據能夠被存放到同一個簇當中,這樣就能夠取得很好的壓縮率。當咱們在BigTable中存儲同一個值的多個不一樣版本時,能夠取得更好的壓縮率。

Caching for read performance

   爲了改進讀性能,tablet服務器使用兩個層次的緩存。Scan緩存是一個高層次的緩存,它緩存了「鍵–值」對,這些「鍵–值」對是由tablet服務器代碼的SSTable接口返回的。Block緩存是比較低層次的緩存,它緩存了從GFS當中讀取的SSTable塊。Scan緩存對於那些頻繁讀取相同數據的應用來講是很是有用的。Block緩存對於那些傾向於讀取與本身最近讀取數據臨近的數據的應用來講,是比較有用的,好比順序讀取,或者隨機讀取屬於同一個locality group中的不一樣的列。

Bloom filters

    正如5.3節闡述的那樣,一個讀操做必須從構成一個tablet的當前狀態的全部SSTable中讀取數據。若是這些SSTable不在內存中,咱們就不得不須要不少磁盤訪問。咱們經過下面的方式來減小磁盤訪問,即容許客戶端來肯定,爲某個特定locality group中的SSTable建立Bloom filter[7]。一個Bloom filter容許咱們詢問,一個SSTabble是否包含屬於指定的「行–列隊」的特定的數據。對於某個特定的應用,一個用來存儲Bloom filter的不多量的tablet服務器內存空間,均可以極大減小讀操做的磁盤訪問次數。咱們使用Bloom filter也意味着,許多針對目前不存在的行或列的查詢,根本就不須要訪問磁盤。

Commit-log implementation

        若是咱們爲每一個tablet都設置一個單獨的文件來保存提交日誌,那麼,在GFS中,會有大量的文件併發寫操做。取決於每一個GFS服務器底層文件系統的實現方式,這些寫操做會引發大量的磁盤訪問。除此之外,讓每一個tablet都有一個單獨的日子文件,會下降分組提交優化的效率。爲了解決這些問題,咱們對每一個tablet服務器具有一個獨立日誌文件這種方式進行了補充,不是把更新都寫入相應tablet的獨立文件中,而是把幾個不一樣tablet的更新內容都添加到一個一樣的物理日誌文件中[18][20]。

        使用單個日誌文件,明顯改善了普通操做時的性能收益,可是,它使得故障恢復變得複雜起來。當一個tablet服務器死亡,它上面承載的tablet會被從新分配到其餘多個tablet服務器,每一個tablet服務器一般只接收一部分tablet。爲了給一個tablet恢復狀態,新的tablet服務器須要根據原來tablet服務器中記載的提交日誌文件,爲這個tablet從新執行一遍更新操做。可是,針對這些tablet的更新操做的日子記錄,都混合存放在一個日誌文件中。一種方法是,讓新的tablet服務器完整地讀取一份提交日誌文件,而後,只把恢復這個tablet時所須要的日誌記錄讀取出來,完成恢復。可是,在這種機制下,若是有100個機器,每一個都被分配了來自死亡tablet服務器的一個單獨的tablet,那麼,這個日誌文件就必須被重複讀取100遍。

        咱們經過如下的方式來避免日誌的重複讀寫:首先以鍵(表,行名稱,日誌順序號)的順序對日誌文件的條目(entry)進行排序。在排序獲得的結果中,全部針對某個特定tablet的更新都是連續存放的,所以,能夠經過一次磁盤尋找,而後順序批量讀取數據,這種方法具備較高的效率。爲了實現並行排序,咱們把日子文本分割成64MB爲單位的分段,在不一樣的tablet服務器上對每一個分段進行並行排序。主服務器會對排序過程進行協調,當一個tablet服務器表示須要從一些提交日誌文件中恢復數據時,就須要啓動排序過程。

        書寫提交日誌到GFS中去,因爲不少緣由(好比GFS服務器上包含不少衝突操做,或者網絡擁塞),有時會帶來性能上的瓶頸。爲了使得更新免受GFS延遲的影響,每一個tablet服務器實際上有兩個日子書寫線程,每一個線程都書寫到它本身的日誌中。在運行時,只有一個進程處於工做狀態。若是當前活躍的日誌書寫線程性能比較差,那麼,就切換到另外一個日誌書寫線程。在更新日誌隊列中的更新就會被這個新激活的線程書寫。日誌條目包含了序號,這就能夠幫助恢復過程刪除那些因爲線程切換而致使的重複的日誌記錄。

Speeding up tablet recovery

    若是主服務器把一個tablet從一個tablet服務器轉移到另外一個tablet服務器。這個源tablet服務器就對這個tablet作一個次壓縮(minor compaction)。經過減小tablet服務器中的提交日誌中的未壓縮狀態的數量,壓縮過程減小了恢復時間。在完成這個壓縮過程之後,這個源tablet服務器就中止提供針對這個tablet的服務。在它實際上卸載這個tablet以前,這個源tablet服務器要作另外一個次壓縮,來刪除本tablet服務器的日誌中任何未壓縮的狀態,這些未壓縮狀態是在第一個次壓縮進行過程當中產生的。當第二個次壓縮完成時,這個tablet就能夠被加載到另外一個tablet服務器,而不須要任何日誌條目的恢復。

Exploiting immutability

        除了SSTable緩存,BigTable系統的其餘部分也已經被簡化,這些簡化基於這樣一個事實,即咱們所產生的全部SSTable都是不變的。例如,當咱們從SSTable中讀取數據時,不須要進行任何文件系統訪問的同步。結果是,針對行級別的併發控制能夠高效地執行。惟一發生變化的數據結構是memtable,它同時被讀操做和寫操做訪問。爲了減小讀取memtable過程當中的衝突,咱們使得每一個memtable行採起」copy-on-write」,而且容許讀和寫操做並行執行。

        因爲SSTable是不可變的,永久性刪除數據的問題就轉變成,收集廢棄的SSTable。每一個tablet的SSTable,都會在METADATA表中進行註冊。主服務器移除廢棄的SSTable,把它標記爲垃圾數據集合。

        最後,SSTable的不可變性,容許咱們更快地分裂tablet,而不是爲每一個子tablet生成一個新的SSTable集合。咱們讓子tablet和父tablet共享一個SSTable集合。

7 Performance Evaluation

        咱們創建了一個BigTable簇,它具備N個tablet服務器,咱們改變N的值,從而測試BigTable的性能和可擴展性。Tablet服務器的配置爲,1GB內存,而且把數據寫到GFS單元格中,這個GFS單元格包含了1786個機器,每一個機器具有400GB IDE硬盤。咱們讓N個客戶端機器產生針對BigTable的負載,從而實現測試。須要指出的是,這裏咱們採用的客戶端的數量和tablet服務器的數量是相等的,從而保證客戶端不會成爲瓶頸。每一個機器都有兩個雙核Opteron 2GHz芯片、足夠的物理內存(從而可以容納工做集產生的數據)和GB帶寬的網絡鏈接。這些機器被安排爲兩層樹型交換網絡,在根部的帶寬能夠達到100-200Gbps。全部這些機器都採用相同的配置,都在同一個域內,所以,任何兩臺機器之間的通信時間都不會超過1微秒。

        Tablet服務器、主服務器、測試客戶端和GFS服務器都在同一個機器集合上運行。每一個機器都運行一個GFS服務器。同時,一些機器還會另外運行一個tablet服務器,一個客戶端進程。

        R是BigTable的不一樣值的行鍵的數量,在選擇R的值的時候,須要確保每一個benchmark在每一個tablet服務器上讀或寫大約1GB的數據量。

        負責順序寫的benchmark,使用名稱從0到R-1的行鍵。行鍵的空間被分區成10N個等尺寸區間。這些區間被中央調度器分配到N個客戶端,一旦,某個客戶端已經處理完前面分配到的區間後,中央調度器就當即給這個客戶端分配另外一個區間。這種動態分配,能夠減輕其餘運行於當前機器上的進程對該機器的影響。咱們在每一個行鍵下面,寫了一個單個字符串。每一個字符串都是隨機生成的,所以,不具有可壓縮性。除此之外,在不一樣行鍵下面的字符串都是不一樣的,這樣就不會存在跨行壓縮。負責隨機寫的benchmark也是相似的,初了行鍵在寫以前要以R爲模數進行哈希操做,從而使得在整個benchmark期間,寫操做負載能夠均勻分佈到整個行空間內。

        負責順序讀的benchmark產生行鍵的方式,也和負責順序寫的benchmark相似。可是,順序讀benchmark不是在行鍵下面寫數據,而是讀取存儲在行鍵下面的字符串,這些字符串是由前面的順序寫benchmark寫入的。相似地,隨機讀benchmark會以隨機的方式讀取隨機寫benchmark所寫入的數據。

        Scan benchmark和順序讀benchmark相似,可是,使用了由BigTable API所提供的支持,來掃描屬於某個域區間內的全部值。使用一個scan,減小了由benchmark所執行的RPC的數量,由於,在Scan中,只須要一個RPC就能夠從tablet服務器中獲取大量順序值。

        隨機讀(mem) benchmark和隨機讀benchmark相似,可是,包含這個benchmark數據的局部羣組,被標記爲in-memory,所以,它是從內存中讀取所需數據,而不是從GFS中讀取數據。對這個benchmark而言,咱們把每一個tablet服務器所包含數據的數量,從1GB減小到100MB,從而能夠很好地裝入tablet服務器可用內存中。

Google Bigtable,廈門大學,廈門大學計算機系,數據庫實驗室,林子雨

    圖6顯示了,當讀或寫1000字節的數據到BigTable中時,咱們的benchmark的性能。表格內容顯示了每一個tablet服務器每秒的操做的數量。圖顯示了每秒的操做的總數量。

Single-tablet-server performance

        讓咱們首先考慮只有一個tablet服務器的性能。隨機讀的性能要比其餘類型的操做的性能都要差一個數量級,甚至差更多。每一個隨機讀操做包含了,把一個64KB的SSTable塊經過網絡從GFS傳輸到一個tablet服務器,在這個塊中,只有1000字節的數據會被使用。Tablet服務器大約每秒執行1200個操做,這會致使從GFS須要讀取大約75MB/s。在這個過程當中,帶寬是足夠的。許多具備這種訪問模式的BigTable應用都把塊大小設置爲更小的值8KB。

        從內存讀取數據的隨機讀會更快一些,由於,每一個1000字節讀都是從tablet服務器內存當中讀取,而不須要從GFS當中讀取64KB的數據。

        隨機和順序寫執行的性能要好於隨機讀,由於,每一個tablet服務器都把全部到達的寫都追加到一個單獨的提交日誌中,而且使用分組提交,從而使獲得GFS的寫操做能夠流水化。在隨機寫和順序寫之間,沒有明顯的性能差異。在兩種情形下,全部的寫都記錄在同一個提交日誌中。

        順序讀的性能要好於隨機讀,由於從GFS中獲取的每64KB SSTable塊,會被存儲到塊緩存中,它能夠爲後面的64個讀操做服務。

       Scan操做會更快,由於,針對單個RPC,tablet服務器能夠返回大量的值,所以,RPC開銷就能夠分攤到大量的值當中。

Scaling

當咱們在系統中把tablet服務器的數量從1增長到500的過程當中,累計吞吐量急劇增長,一般以100倍的規模。例如,隨着tablet服務器增加了500倍,針對內存的隨機讀的性能,增加了大約300倍,之因此會發生這種狀況,由於這個benchmark的性能瓶頸是單個tablet服務器的CPU。

可是,性能不會線性增加。對於多數benchmark來講,當把tablet服務器的數量從1增長到50時,每一個服務器的吞吐量有顯著的下降。這個問題,是由多服務器環境中,負載不均衡引發的,一般因爲有其餘進程爭搶CPU資源和網絡帶寬。咱們的負載均衡算法努力解決這個問題,可是,沒法實現完美的目標,主要緣由在於:第一,從新負載均衡有時候會被禁止,這樣作能夠減小tablet遷移的數量(當一個tablet遷移時,在短期內是不可用的,一般是一秒);第二,咱們的benchmark的負載是動態變化的。

隨機讀benchmark顯示了最差的可擴展性。當服務器數量增長500倍時,累計吞吐量的增加只有100倍左右。致使這個問題的緣由在於,對於每一個1000字節的讀操做,咱們都會轉移一個64KB的塊。這個數據轉移使得咱們的GB級別的網絡很快達到飽和,這樣,當咱們增長機器的數量時,單個服務器的吞吐量就會很快下降。

8 Real applications

    截止到2006年8月,已經又388個非測試的BigTable簇運行在不一樣的Google服務器簇裏,包括總共大約24500個tablet服務器。表1顯示了每一個簇中的tablet服務器的大概分佈。許多簇都是用於開發目的,所以,在不少時間內都是空閒的。一組包含14個繁忙簇(包含8069個tablet服務器),每秒鐘的累積負載是120萬個請求。其中,到達的RPC流量是741MB/s,出去的RPC流量大約是16GB/s。表2提供了一些關於當前正在使用的表的數據。一些表存儲爲用戶服務的數據,而其餘表則存儲爲批處理服務的數據。在總尺寸、平均單元格尺寸、從內存服務的數據的百分比以及表模式的複雜性方面,這些表區別很大。下面,咱們將要分別描述三個產品團隊如何使用BigTable。

Google Bigtable,廈門大學,廈門大學計算機系,數據庫實驗室,林子雨

Google Bigtable,廈門大學,廈門大學計算機系,數據庫實驗室,林子雨

8.1 Google Analytics

        Google Analytics是一種服務,它幫助網站管理者分析網站流量模式。它提供了彙總分析,好比,天天不一樣訪問者的數量,以及天天每一個URL的網頁視圖的數量,以及網站流量報告,好比瀏覽了某個網頁之後發生購買行爲的用戶的數量。

        爲了支持這項服務,網站管理員在網頁中嵌入了一個小的Javascript程序。每當頁面被訪問時,都會觸發這個Javascript程序。它把關於這個用戶訪問的全部相關信息都記錄在Google Analytics中,好比用戶標識以及被訪問的網頁的信息。Google Analytics分析這些數據,並提供給網站管理員訪問。

        咱們簡單地描述Google Analytics所使用的兩個表。網站點擊表(200TB)爲每一個用戶訪問都維護了一個行。行的名稱是一個元祖,它包含了網站的名稱以及session被建立的時間。這個表模式保證了,訪問同一個WEB站點的session都是臨近的,而且以時間順序進行存儲。這個表的壓縮率能夠達到14%。

        彙總表(大約20TB)包含了針對每一個網站的不一樣的彙總信息。這個表是從網站點擊表中經過週期性地運行MapReduce做業而獲得的。每一個MapReduce做業從網站點擊表當中抽取最近的session信息。系統的總吞吐量,受到了GFS吞吐量的限制。這個表的壓縮率在29%左右。

8.2 Google Earth

        Google提供不少服務,它支持用戶訪問高清晰度的衛星圖片,或者經過基於瀏覽器的Google Maps接口,或者經過定製的客戶端軟件Google Earth。這些產品容許用戶在地球表面進行導航。該產品支持在不一樣清晰度下查看和標註地圖信息。該系統採用一個表進行數據預處理,用另外一個表位用戶提供數據服務。

        這個預處理管道使用一個表來存儲衛星圖片。在預處理過程當中,影像數據被清洗並轉換成最後的服務數據。這個表包含了大約70TB的數據,所以,是從磁盤訪問的。影像數據都是通過壓縮的,所以,BigTable就不存在數據壓縮了。

        影像表中的每行,都對應一個單個的地理片斷。行被命名,以保證相鄰的地理分段在存儲時彼此接近。表包含了一個列家族來跟蹤每一個分段的數據。這個列家族包含了大量的列,基本上爲每一個原始影像建立一個列。由於,每一個分段只是從少許幾個列中的影像構建獲得的,所以,這個列家族很稀疏。

        這個預處理管道嚴重依賴於針對BigTable的MapReduce操做來轉換數據。在這些MapReduce做業運行期間,整個系統的每一個服務器大約處理1MB/秒的數據。

        這個服務系統使用一個表來對存儲在GFS中的數據創建索引。這個表相對比較小,大約500GB。可是,每一個數據中心每秒鐘必須以很低的延遲處理成千上萬個請求。於是,這個表一般被重複存放到多個tablet服務器上,而且包含了內存列家族。

8.3 Personalized Search

        Personalized search是一種服務,它記錄了用戶查詢和點擊數據,涵蓋了各個方面的Google屬性,好比,網頁搜索、圖片和新聞。用戶能夠瀏覽他們本身的訪問歷史,他們能夠要求根據Google使用歷史模式來得到個性化的搜索結果。

        Personalized search把全部的用戶數據都存放在BigTable中。每一個用戶都有一個獨特的用戶ID,並被分配了以這個用戶ID爲名字的行。每種類型的動做都會存儲到特定的列家族中,好比,有一個列家族存儲了全部的網頁查詢。每一個數據元素都把這個動做發生的時間做爲BigTable的時間戳。Personalized search在BigTable上使用MapReduce產生用戶的profile。這些用戶profile用來協助生成個性化的用戶搜索結果。

        Personalized Search的數據被分佈到多個BigTable簇,來增長可用性,減小由距離而產生的延遲。Personalized Search最初構建了基於BigTable的客戶端副本模式,從而保證全部副本的最終一致性。當前的系統使用了一個複製子系統,它是內嵌到服務器端的。

        Personalized Search存儲系統的設計,容許其餘分組增長新的用戶信息到他們本身的列中,這個系統當前正在被許多Google屬性使用,這些屬性須要存儲用戶的配置信息和設置。在多個分組之間共享一個表,致使了列家族數量比較大。爲了幫助支持共享,咱們爲BigTable增長了一個簡單的配額機制,從而對共享表當中某個特定應用可使用的存儲空間進行限制。這種機制爲每一個用戶在使用本系統的不一樣的產品分組之間創建了隔離。

9 Lessons

        在設計、實現、維護和支持BigTable的過程當中,咱們收穫了有益的經驗,而且得到了幾個有意思的教訓。

        咱們獲得的一個教訓是,大的分佈式系統很發生多種錯誤,不只是其餘分佈式系統常常遇到的標準的網絡分割和故障。例如,咱們已經遇到問題,他們是由如下緣由引發的:內存和網絡故障、大的時鐘扭曲、機器掛起、咱們所使用的其餘系統(好比Chubby)中存在的故障、GFS配額當中的溢出以及計劃或非計劃之中的硬件維護。隨着咱們得到了更多的針對這些問題的經驗,咱們已經經過改變不一樣的協議來解決他們。例如,咱們爲RPC機制增長了checksumming。咱們經過移除一部分系統針對另外一部分系統所作的假設,也解決了一些問題。例如,咱們取消了假設一個給定的Chubby操做只返回一個固定錯誤集合。

        咱們得到的另外一個教訓是,在很清楚地知道如何使用一個新特性以前,不要隨便增長這個新特性。例如,咱們最初計劃在咱們的應用API當中支持通用的事務。由於咱們不會當即用到這種功能,因此,咱們沒有實現它。如今咱們有許多應用都是運行在BigTable之上,咱們就能夠考察他們的應用需求,發現不少應用只須要針對單個記錄的事務。當人們須要分佈式事務時,最主要的用途就在於維護二級索引,咱們就考慮增長一個特定的機制來知足這種需求。在通用性方面,這種特定機制會比通用事務模型差一些,可是,它更高效,尤爲是對於那些須要跨越多個行的更新而言。

        從支持BigTable運行中得到的一個比較實際的教訓是,合適的系統級別的監視的重要性,即監視BigTable本身,也監視運行在BigTable上的進程。例如,咱們擴展了咱們的RPC系統,從而使得對一些RPC樣本,它會詳細跟蹤記錄針對該RPC的重要動做。這種特性已經容許咱們探測和解決許多問題,好比針對tablet數據結構的鎖衝突,當執行BigTable更新時的慢寫,以及當METADATA tablet不可用時,訪問METADATA表發生的阻塞。說明監視比較有用的另外一個例子是,每一個BigTable簇都是在Chubby中註冊的。這就容許咱們跟蹤全部的簇,發現這些簇的大小,看看它們當前使用的是咱們軟件的哪一個版本,以及是否存在一些預料以外的問題,好比很大的延遲。

        咱們所得到的最重要的教訓就是簡單設計的價值。假設咱們系統的尺寸是大約10萬行非測試代碼,以及這些代碼會隨着時間演化,咱們發現代碼和設計的清晰性對於代碼和系統維護具備重要的幫助。一個例子是咱們的tablet服務器成員協議。咱們的第一個協議很簡單,主服務器週期性地發佈租約給tablet服務器,若是tablet服務器發現租約到期就自殺。不幸的是,當存在網絡問題時,這種協議極大下降了系統的可用性,而且對於主服務器的恢復時間也很敏感。咱們前後幾回更改了協議的設計,直到找到一個好的協議。可是,這個比較好的協議,太複雜,而且依賴於那些不多被其餘應用使用的Chubby功能。咱們發現,咱們花費了大量的時間來調試各類晦澀的案例。最後,咱們廢棄了這個協議,轉向採用一個比較簡單的新的協議,它只依賴那些常常被使用的Chubby功能。

10 Related Work

        Boxwood項目[24]具備一些和Chubby、GFS以及BigTable重疊的組件,由於Boxwood支持分佈式協議和分佈式B樹存儲。在每一個發生重疊的領域中,Boxwood看起來彷佛針對的是Google所提供服務的低一層次的服務。Boxwood項目的目標是提供構建高層次服務的基礎架構,好比文件系統或數據庫,而BigTable的目標是直接支持那些須要存儲數據的客戶端應用。

        許多最近的計劃,已經解決了在廣域網內提供分佈式存儲和高層次服務的問題。這些計劃包括,在分佈式哈希表方面的工做,好比項目CAN[29]、CHORD[32]、Tapestry[37]和Pastry[30]。這些系統解決的問題,在BigTable中沒有出現,好比高可用性帶寬、不可信的參與者或頻繁地重配置。分佈式控制和理想的零錯誤不是BigTable的設計目標。

        就能夠提供給應用開發者的分佈式存儲模型而言,咱們認爲,分佈式B樹所提供的「鍵-值對」模型或者分佈式哈希表具備很大的侷限性。「鍵-值對」是一個有用的積木,可是,它不該該是能夠提供給應用開發者的惟一的積木。咱們所能提供的模型比簡單的「鍵-值對」更加豐富,而且支持稀疏的辦結構化數據。可是,它是很是簡單的,而且足以支持很是高效的平面文件表示,而且它足夠透明,容許用戶來調節系統重要的行爲。

        有幾個數據庫開發商已經開發了並行數據庫,它能夠存儲大量的數據。Oracle的Real Application Cluster數據庫[27],使用共享的磁盤來存儲數據(BigTable使用GFS),而且使用一個分佈式的鎖管理器(BigTable使用Chubby)。IBM的DB2 Parallel Edition[4]是基於非共享[33]的體系架構,這一點和BigTable相似。每一個DB2服務器負責表中行的一個子集,它被存儲在一個局部關係數據庫中。IBM的DB2 Parallel Edition和Oracle的Real Application Cluster都提供了完整的事務模型。

        BigTable局部分組實現了和其餘一些系統相似的壓縮和磁盤讀性能,這些系統在磁盤上存儲數據室,採用基於列而不是基於行的存儲,包括C-store[1,34]和商業化產品,好比Sybase IQ[15,36],SenSage[31],KDB+[32],以及在MonetDB/X100[38]當中的ColumnBM存儲層。另外一個把數據垂直和水平分區到平面文件中而且取得了很好的數據壓縮率的系統是,AT&T的Daytona數據庫[19]。局部分組不支持CPU緩存級別的優化,好比那些在Ailamaki[2]中描述的。

        BigTable使用memtable和SSTable來存儲tablet更新的方式,和Log-Structured Merge Tree[26]用來存儲索引更新的方式是相似的。在這兩個系統中,排序的數據在寫入到磁盤以前是存放在內存之中的,讀操做必須把來自磁盤和內存的數據進行合併。

        C-Store和BigTable具備不少類似的特性:兩個系統都使用非共享的體系架構,都有兩個不一樣的數據結構,一個是爲存放最近的寫操做,一個是爲存放長期的數據,而且設計了把數據從一個結構轉移到另外一個結構的機制。可是,這兩個系統在API方面具備很大的區別:C-Store就像一個關係型的數據庫,而BigTable提供了一個低層次的讀和寫接口,而且被設計成在每一個服務器上每秒鐘內提供成千上萬的這種操做。C-Store也是一個讀優化的關係型DBMS,而BigTable對讀敏感和寫敏感的應用都提供了很好的性能。

        BigTable的負載均衡器,必須解決負載均衡和內存均衡問題,這也是非共享數據庫[11,35]一般面臨的問題。咱們的問題更加簡單一些:(1)咱們不考慮同一個數據存在多個副本的情形,咱們可能採用視圖或索引的形式以另外一種方式來看待副本;(2)咱們讓用戶告訴咱們,什麼數據應該放在內存中,什麼數據應該放在磁盤上,而不是系統本身盡力去猜想數據的存放位置;(3)咱們沒有複雜的查詢優化機制,也不執行復雜的查詢。

11 Conclusions

        咱們已經描述了BigTable,一個爲Google存儲數據的分佈式存系統。自從2005年4月開始,BigTable簇已經在實際生產系統中使用。在那以前,咱們已經投入了7個person-years在設計和開發上。截止2006年8月,有超過60項計劃正在使用BigTable。咱們的用戶喜歡BigTable 提供的高性能和高可用性。當用戶的資源需求隨着時間變化時,他們只須要簡單地往系統中添加機器,就能夠實現服務器簇的擴展。

        鑑於BigTable的不一樣尋常的接口,一個有意思的問題是,咱們的用戶適應BigTable的過程是多麼艱難。新的用戶有時候不知道如何很好地使用BigTable提供的接口,尤爲是,他們已經習慣使用支持通用事務的關係型數據庫。可是,許多Google產品成功地使用BigTable來存放數據這樣一個事實,已經說明BigTable設計的成功。

        咱們正在考慮增長其餘幾個額外的BigTable功能,好比支持二級索引,以及一個基礎框架,它能夠支持構建跨數據中心分佈BigTable數據。咱們已經開始把BigTable做爲一個服務提供給產品組,從而使得每一個組都不須要維護他們本身的簇。隨着咱們的服務簇的擴展,咱們須要處理更多的BigTable內部的資源共享的問題。

        

最後值得一提的是,咱們發如今google構建咱們的存儲解決方案有很大的優點。咱們不只有足夠的靈活度爲bigtable設計數據模型,咱們還可以徹底控制BigTable的實現,甚至Bigtable依賴的其它google基礎設施。這些權限意味着一旦(bigtable或其依賴的基礎設施)出現了瓶頸和低效之處,咱們可以及時解決。

 

Acknowledgements

We thank the anonymous reviewers, David Nagle, and our shepherd Brad Calder, for their feedback on this paper. The Bigtable system has benefited greatly from the
feedback of our many users within Google. In addition, we thank the following people for their contributions to Bigtable: Dan Aguayo, Sameer Ajmani, Zhifeng Chen,
Bill Coughran, Mike Epstein, Healfdene Goguen, Robert Griesemer, Jeremy Hylton, Josh Hyman, Alex Khesin, Joanna Kulik, Alberto Lerner, Sherry Listgarten, Mike
Maloney, Eduardo Pinheiro, Kathy Polizzi, Frank Yellin, and Arthur Zwiegincew.(廈門大學林子雨翻譯 標註:致謝就不翻譯了啊)

References

[1] ABADI, D. J., MADDEN, S. R., AND FERREIRA,M. C. Integrating compression and execution in columnoriented database systems. Proc. of SIGMOD (2006).
[2] AILAMAKI, A., DEWITT, D. J., HILL, M. D., AND SKOUNAKIS, M. Weaving relations for cache performance. In The VLDB Journal (2001), pp. 169–180.
[3] BANGA, G., DRUSCHEL, P., AND MOGUL, J. C. Resource containers: A new facility for resource management in server systems. In Proc. of the 3rd OSDI (Feb.1999), pp. 45–58.
[4] BARU, C. K., FECTEAU, G., GOYAL, A., HSIAO,H., JHINGRAN, A., PADMANABHAN, S., COPELAND, G. P., AND WILSON, W. G. DB2 parallel edition. IBM Systems Journal 34, 2 (1995), 292–322.
[5] BAVIER, A., BOWMAN, M., CHUN, B., CULLER, D., KARLIN, S., PETERSON, L., ROSCOE, T., SPALINK, T.,AND WAWRZONIAK, M. Operating system support for planetary-scale network services. In Proc. of the 1st NSDI (Mar. 2004), pp. 253–266.
[6] BENTLEY, J. L., AND MCILROY, M. D. Data compression using long common strings. In Data Compression Conference (1999), pp. 287–295.
[7] BLOOM, B. H. Space/time trade-offs in hash coding with allowable errors. CACM 13, 7 (1970), 422–426.
[8] BURROWS, M. The Chubby lock service for looselycoupled distributed systems. In Proc. of the 7th OSDI (Nov. 2006).
[9] CHANDRA, T., GRIESEMER, R., AND REDSTONE, J. Paxos made live — An engineering perspective. In Proc. of PODC (2007).
[10] COMER, D. Ubiquitous B-tree. Computing Surveys 11, 2 (June 1979), 121–137.
[11] COPELAND, G. P., ALEXANDER, W., BOUGHTER, E. E., AND KELLER, T. W. Data placement in Bubba. In Proc. of SIGMOD (1988), pp. 99–108.
[12] DEAN, J., AND GHEMAWAT, S. MapReduce: Simplified data processing on large clusters. In Proc. of the 6th OSDI (Dec. 2004), pp. 137–150.
[13] DEWITT, D., KATZ, R., OLKEN, F., SHAPIRO, L., STONEBRAKER, M., AND WOOD, D. Implementation techniques for main memory database systems. In Proc. of SIGMOD (June 1984), pp. 1–8.
[14] DEWITT, D. J., AND GRAY, J. Parallel database systems: The future of high performance database systems. CACM 35, 6 (June 1992), 85–98.
[15] FRENCH, C. D. One size fits all database architectures do not work for DSS. In Proc. of SIGMOD (May 1995), pp. 449–450.
[16] GAWLICK, D., AND KINKADE, D. Varieties of concurrency control in IMS/VS fast path. Database Engineering Bulletin 8, 2 (1985), 3–10.
[17] GHEMAWAT, S., GOBIOFF, H., AND LEUNG, S.-T. The Google file system. In Proc. of the 19th ACM SOSP (Dec.2003), pp. 29–43.
[18] GRAY, J. Notes on database operating systems. In Operating Systems — An Advanced Course, vol. 60 of Lecture Notes in Computer Science. Springer-Verlag, 1978.
[19] GREER, R. Daytona and the fourth-generation language Cymbal. In Proc. of SIGMOD (1999), pp. 525–526.
[20] HAGMANN, R. Reimplementing the Cedar file system using logging and group commit. In Proc. of the 11th SOSP (Dec. 1987), pp. 155–162.
[21] HARTMAN, J. H., AND OUSTERHOUT, J. K. The Zebra striped network file system. In Proc. of the 14th SOSP (Asheville, NC, 1993), pp. 29–43.
[22] KX.COM. kx.com/products/database.php. Product page.
[23] LAMPORT, L. The part-time parliament. ACM TOCS 16,2 (1998), 133–169.
[24] MACCORMICK, J., MURPHY, N., NAJORK, M., THEKKATH, C. A., AND ZHOU, L. Boxwood: Abstractions as the foundation for storage infrastructure. In Proc. of the 6th OSDI (Dec. 2004), pp. 105–120.
[25] MCCARTHY, J. Recursive functions of symbolic expressions and their computation by machine. CACM3, 4 (Apr. 1960), 184–195.
[26] O’NEIL, P., CHENG, E., GAWLICK, D., AND O’NEIL,E. The log-structured merge-tree (LSM-tree). Acta Inf.33, 4 (1996), 351–385.
[27] ORACLE.COM. www.oracle.com/technology/products/-database/clustering/index.html. Product page.
[28] PIKE, R., DORWARD, S., GRIESEMER, R., AND QUINLAN, S. Interpreting the data: Parallel analysis with Sawzall. Scientific Programming Journal 13, 4 (2005),227–298.
[29] RATNASAMY, S., FRANCIS, P., HANDLEY, M., KARP, R., AND SHENKER, S. A scalable content-addressable network. In Proc. of SIGCOMM (Aug. 2001), pp. 161–172.
[30] ROWSTRON, A., AND DRUSCHEL, P. Pastry: Scalable, distributed object location and routing for largescale peer-to-peer systems. In Proc. of Middleware 2001 (Nov. 2001), pp. 329–350.
[31] SENSAGE.COM. sensage.com/products-sensage.htm. Product page.
[32] STOICA, I., MORRIS, R., KARGER, D., KAASHOEK, M. F., AND BALAKRISHNAN, H. Chord: A scalable peer-to-peer lookup service for Internet applications. In Proc. of SIGCOMM (Aug. 2001), pp. 149–160.
[33] STONEBRAKER, M. The case for shared nothing. Database Engineering Bulletin 9, 1 (Mar. 1986), 4–9.
[34] STONEBRAKER, M., ABADI, D. J., BATKIN, A., CHEN, X., CHERNIACK, M., FERREIRA, M., LAU, E., LIN, A., MADDEN, S., O’NEIL, E., O’NEIL, P., RASIN, A., TRAN, N., AND ZDONIK, S. C-Store: A columnoriented DBMS. In Proc. of VLDB (Aug. 2005), pp. 553–564.
[35] STONEBRAKER, M., AOKI, P. M., DEVINE, R., LITWIN, W., AND OLSON, M. A. Mariposa: A new architecture for distributed data. In Proc. of the Tenth ICDE(1994), IEEE Computer Society, pp. 54–65.
[36] SYBASE.COM. www.sybase.com/products/databaseservers/sybaseiq. Product page.
[37] ZHAO, B. Y., KUBIATOWICZ, J., AND JOSEPH, A. D. Tapestry: An infrastructure for fault-tolerant wide-area location and routing. Tech. Rep. UCB/CSD-01-1141, CS Division, UC Berkeley, Apr. 2001.
[38] ZUKOWSKI, M., BONCZ, P. A., NES, N., AND HEMAN, S. MonetDB/X100—A DBMS in the CPU cache. IEEE Data Eng. Bull. 28, 2 (2005), 17–22.

(廈門大學計算機系 林子雨 翻譯)

相關文章
相關標籤/搜索