1. 程式人生 > >Bigtable:一個分散式的結構化資料儲存系統

Bigtable:一個分散式的結構化資料儲存系統

修正了alex翻譯版的幾個欠妥之處
Bigtable
:一個分散式的結構化資料儲存系統

摘要

Bigtable是一個管理結構化資料的分散式儲存系統,它被設計用來處理海量資料:分佈在數千臺通用伺服器上的PB級的資料。Google的很多專案將資料儲存在Bigtable中,包括Web索引、Google EarthGoogle Finance。這些應用對Bigtable提出的要求差異非常大,無論是在資料規模(從URL到網頁到衛星影象)還是在響應速度上(從後端的批量處理到實時資料服務)。儘管應用需求差異很大,但是,針對所有Google這些產品,Bigtable還是成功地提供了一個靈活的、高效能的解決方案。本文描述了Bigtable

提供的簡單的資料模型,利用這個模型,使用者可以動態的控制資料的佈局和格式;並且我們還將描述Bigtable的設計和實現。

介紹

在過去兩年半時間裡,我們設計、實現並部署了一個用於管理結構化資料的分散式的儲存系統—在Google,我們稱之為BigtableBigtable的設計目的是可靠地適應PB級別的資料和成千上萬臺機器。Bigtable已經實現了下面的幾個目標:廣泛的適用性、可擴充套件、高效能和高可用性。已經有超過60Google的產品和專案在使用Bigtable,包括Google AnalyticsGoogle FinanceOrkutPersonalized Search

WritelyGoogle Earth。這些產品使用Bigtable完成迥異的工作負載需求,這些需求從面向吞吐量的批處理作業到對終端使用者而言延時敏感的資料服務。它們使用的Bigtable叢集的配置也有很大的差異,從少數機器到成千上萬臺伺服器,這些伺服器裡最多可儲存幾百TB的資料。

在很多方面,Bigtable和資料庫很類似:它使用了很多資料庫的實現策略。並行資料庫【14】和記憶體資料庫【13】已經具備可擴充套件性和高效能,但是Bigtable提供了一個和這些系統完全不同的介面。Bigtable不支援完整的關係資料模型;與之相反,Bigtable為客戶提供了簡單的資料模型,利用這個模型,客戶可以動態控制資料的佈局和格式

alex注:也就是對BigTable而言,資料是沒有格式的,用資料庫領域的術語說,就是資料沒有Schema,使用者自己去定義Schema,使用者也可以自己推測(alex注:reason about)在底層儲存中展示的資料的位置屬性(alex注:位置相關性可以這樣理解,比如樹狀結構,具有相同字首的資料的存放位置接近。在讀取的時候,可以把這些資料一次讀取出來)。資料用行和列的名字進行索引,名字可以是任意的字串。雖然客戶程式通常會在把各種結構化或半結構化的資料序列化到字串裡,Bigtable同樣將資料視為未經解析的字串。通過仔細選擇資料的模式,客戶可以控制資料的位置。最後,可以通過BigTable的模式引數動態地控制資料讀或寫(control whether to serve data out of memory or from disk)

第二節更詳細地描述了資料模型,第三節概要介紹了客戶端API;第四節簡要介紹了BigTable依賴的底層Google基礎框架;第五節描述了BigTable實現的基本原理;第6節描述了為了提高BigTable的效能而採用的一些精細的調優方法;第7節提供了BigTable的效能資料;第8節講述了幾個Google內部使用BigTable的例子;第9節討論了我們在設計和後期支援過程中得到一些經驗和教訓;最後,在第10節介紹了相關工作,第11節是我們的結論。

資料模型

Bigtable是一個稀疏的、分散式的、持久化儲存的多維度排序Mapalex注:對於程式設計師來說,Map應該不用翻譯了吧。Mapkeyvalue 組成,後面我們直接使用keyvalue,不再另外翻譯了)Map由行關鍵字、列關鍵字以及時間戳索引;Map中的每個value都是一個未經解析的位元組陣列。

(row:string, column:string,time:int64)->string

我們在仔細分析了一個類似Bigtable的系統的種種潛在用途之後,決定選用這個資料模型。我們先舉個具體的例子,這個例子促使我們做了很多設計決策;假設我們想要備份海量的網頁及相關資訊,這些資料可以用於很多不同的專案,我們姑且稱這個特殊的表為Webtable。在Webtable裡,我們使用URL作為行關鍵字,使用網頁的各種屬性(aspect)作為列名,網頁的內容存在“contents:”列中,並用獲取該網頁的時間戳作為標識(alex注:即按照獲取時間不同,儲存了多個版本的網頁資料),如圖一所示。

圖一:一個儲存Web網頁的例子的表的片斷。行名是一個反向URLcontents列族容納的是網頁的內容,anchor列族容納引用該網頁的錨鏈接文字。CNN的主頁被Sports IllustraterMY-look的主頁引用,因此該行包含了名為“anchor:cnnsi.com”和“anchhor:my.look.ca”的列。每個錨鏈接資料項只有一個版本alex注:注意時間戳標識了列的版本,t9t8分別標識了兩個錨鏈接的版本);而contents列則有三個版本,分別由時間戳t3t5,和t6標識。

表中的行關鍵字是任意字串(目前支援最大64KB的字串,但是對大多數使用者,10-100個位元組就足夠了)。在單一行關鍵字下的每一個讀或者寫操作都是原子的(不管在這一行裡被讀或者寫的不同列的數目),這個設計決策能夠使使用者很容易地推測(reason about)對同一個行進行併發更新操作時的系統行為。

Bigtable通過行關鍵字的字典順序來維護資料。表中一定範圍內的行被動態分割槽。每個分割槽叫做一個”Tablet”,Tablet是資料分佈和負載均衡的單位。這樣做的結果是,讀取一定範圍內的少數行很高效,並且往往只需要跟少數機器通訊。使用者可以通過選擇他們的行關鍵字來開發這種特性,這樣可以為他們的資料訪問獲得好的本地性(get good locality)。舉例來說,我們在關鍵字com.google.maps/index.html的索引下為maps.google.com/index.htm儲存資料。把相同的域中的網頁儲存在連續的區域可以讓一些主機和域名的分析更加有效。

列族

列關鍵字組成的集合叫做“列族“,列族構成了訪問控制的基本單位。存放在同一列族下的所有資料通常都屬於同一個型別(我們把同一個列族下的資料壓縮在一起)。列族必須先建立,然後才能在列族中任何的列關鍵字下存放資料;列族建立後,其中的任何一個列關鍵字下都可以存放資料。我們的意圖是,一張表中不同列族的數目要小(最多幾百個),並且列族在操作中很少改變。與此相反,一張表可以有無限多個列。

列關鍵字的命名語法如下:列族:限定詞。列族的名字必須是可列印的字串,但是限定詞可以是任意字串。比如,Webtable有個列族language,用來存放撰寫網頁的語言。我們在language列族中只使用一個列關鍵字,用來存放每個網頁的語言標識IDWebtable中另一個有用的列族是anchor;這個列族的每一個列關鍵字代表單獨一個錨鏈接,如圖一所示。限定詞是引用該網頁的站點名;資料項內容是連結文字。

訪問控制、磁碟和記憶體的計數都是在列族層面進行的。在我們的Webtable的例子中,上述的控制權限能幫助我們管理不同型別的應用:一些應用可以新增新的基本資料、一些可以讀取基本資料並建立派生的列族、一些則只允許瀏覽現存資料(甚至可能因為隱私的原因不能瀏覽所有現存列族)。

時間戳

Bigtable中,每一個數據項都可以包含同一資料的不同版本;這些版本通過時間戳來索引。Bigtable時間戳是64位整型數。時間戳可由Bigtable指定,這種情況下時間戳代表精確到毫秒的“實時”時間,或者該值由庫戶程式明確指定。需要避免衝突的程式必須自己生成一個唯一的時間戳。資料項中不同版本按照時間戳倒序排列,所以最新的版本可以被先讀到。

為了減輕多個版本資料的管理負擔,我們對每一個列族提供兩個設定引數,Bigtable通過這兩個引數可以對廢棄版本的資料進行自動垃圾收集。使用者既可以指定只儲存最後n個版本的資料,也可以只儲存“足夠新”的版本的資料(比如,只儲存最近7天的內容寫入的資料)。

在我們的例子Webtable中,我們將儲存在contents:列中爬蟲經過的頁面的時間戳設定為這個版本的頁面被實際爬過的時(alex:contents:列儲存的時間戳資訊是網路爬蟲抓取一個頁面的時間)。上面提及的垃圾收集機制可以讓我們只保留每個網頁的最近三個版本。

3 API

Bigtable提供了建立和刪除表以及列族的API函式。Bigtable還提供了修改叢集、表和列族的元資料的API,比如修改訪問許可權。

// Open the table

Table *T = OpenOrDie("/bigtable/web/webtable");

// Write a new anchor and delete an old anchor

RowMutation r1(T, "com.cnn.www");

r1.Set("anchor:www.c-span.org", "CNN");

r1.Delete("anchor:www.abc.com");

Operation op;

Apply(&op, &r1);

客戶程式可以對Bigtable進行如下的操作:寫入或者刪除Bigtable中的值、從個別行中查詢值、或者遍歷表中的一個數據子集。圖2中的C++程式碼使用RowMutation抽象物件執行一系列的更新操作。(為了保持示例簡潔,我們省略了無關細節)。對Apply的呼叫執行了了對Webtable的一個原子修改(mutation)操作:它為www.cnn.com增加了一個錨點,同時刪除了另外一個錨點。

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 %s\n",

scanner.RowName(),

stream->ColumnName(),

stream->MicroTimestamp(),

stream->Value());

}

中的C++程式碼使用Scanner抽象物件遍歷一個特定行內的所有錨點。客戶程式可以遍歷多個列族,有幾種機制可以對掃描輸出的行、列和時間戳進行限制。例如,我們可以限制上面的掃描,讓它只輸出那些列匹配正則表示式*.cnn.com的錨點,或者那些時間戳在當前時間前10天的錨點。

Bigtable還支援一些其它的特性,這些特性允許使用者以更復雜的方法操作資料。首先,Bigtable支援單行上事務處理,利用這個功能,使用者可以對儲存在一個單獨行關鍵字下的資料執行原子性的讀取-更新-寫入操作。雖然Bigtable提供了一個允許使用者跨行關鍵字(at the clients?)批量寫入的介面,但是,Bigtable目前還不支援通用的跨行事務處理。其次,Bigtable允許把資料項用做整數計數器。最後,Bigtable支援在伺服器的地址空間內執行指令碼程式。指令碼程式使用Google開發的用於資料處理的Sawzall語言【28】書寫。目前,我們基於SawzallAPI還不允許客戶指令碼將資料寫回Bigtable,但是它允許多種形式的資料轉換、基於任意表達式的資料過濾、以及通過多種操作符的彙總歸納。

Bigtable可以和MapReduce12】一起使用,MapReduceGoogle開發的執行大規模平行計算的框架。我們已經開發了一套封裝器(wrapper),這些封裝器使Bigtable既可以作為MapReduce作業的源輸入也可以作為目標輸出輸出。

4 BigTable構件

Bigtable是建立在一些其他Google基礎架構之上的。BigTable使用Google分散式檔案系統(GFS)17】儲存日誌和資料檔案。BigTable叢集往往執行在一個共享的機器池中,池中的機器還會執行其它各種各樣的分散式應用程式,BigTable的程序經常要和其它應用的程序共享機器。BigTable依賴叢集管理系統在共享機器上排程作業、管理資源、處理機器的故障、以及監視機器的狀態。

SSTable檔案格式

BigTable資料在內部使用Google SSTable檔案格式儲存。SSTable提供一個從鍵(key)到值(value)的持久化的、已排序、不可更改的對映(Map),這裡的keyvalue 的都是任意的位元組(Byte)串。對SSTable提供瞭如下操作:查詢與一個指定key值相關的value,或者遍歷指定key值範圍內的所有鍵值對。從內部看,SSTable是一連串的資料塊(通常每個塊的大小是64KB,但是這個大小是可以配置的)。SSTable使用塊索引(通常儲存在SSTable 的最後)來定位資料塊;在開啟SSTable的時候,索引被載入到記憶體。一次查詢可以通過一次磁碟搜尋完成:首先執行二分查詢在記憶體索引裡找到合適資料塊的位置,然後在從硬碟中讀取合適的資料塊。也可以選擇把整個SSTable都對映到記憶體中,這樣就可以在不用訪問硬碟的情況下執行查詢搜尋了。

Chubby分散式鎖服務

BigTable還依賴一個高可用的、持久化的分散式鎖服務元件,叫做Chubby8】。一個Chubby服務包括了個活動的副本,其中一個副本被選為Master,並且積極處理請求。只有在大多數副本正常執行,並且彼此之間能夠互相通訊的情況下,Chubby服務才是可用的。當有副本失效的時候,出現故障時Chubby使用Paxos演算法【9,23】保證副本的一致性。Chubby提供了一個名字空間,裡面包括了目錄和小檔案。每個目錄或者檔案可以當成一個鎖使用,對檔案的讀寫操作都是原子的。Chubby客戶程式庫提供對Chubby檔案的一致性快取。每個Chubby客戶程式都維護一個與Chubby服務的會話。如果客戶程式不能在租約到期的時間內重新簽訂會話租約,這個會話就過期失效了(A clients session expires if it is unable to renew its session lease within the lease expiration time.)。當一個客戶會話失效時,它擁有的鎖和開啟的檔案控制代碼都失效了。Chubby客戶程式可以在Chubby檔案和目錄上註冊回撥函式,當檔案或目錄改變、或者會話過期時,回撥函式會通知客戶程式。

Bigtable使用Chubby完成以下各種任務:保證在任意時間最多隻有一個活動的Master;儲存BigTable資料的載入程式的位置(參考5.1節);發現tablet伺服器,以及在Tablet伺服器失效時進行善後(5.2節);儲存BigTable的模式資訊(每張表的列族資訊);以及儲存訪問控制列表。如果Chubby長時間無法訪問,BigTable就會失效。最近我們在跨越11Chubby服務例項的14BigTable叢集上測量了這個影響。Bigtable伺服器時鐘的平均比率是0.0047%,在這期間由於Chubby不可用而導致BigTable中的部分資料不能訪問(Chubby不能訪問的原因可能是Chubby本身失效或者網路問題)。單個叢集裡受Chubby失效影響最大的百分比是0.0326%

實現

Bigtable的實現有三個主要的元件:連結到每個客戶程式的庫、一個Master伺服器和多個tablet伺服器。在一個叢集中可以動態地新增(或者刪除)一個tablet伺服器來適應工作負載的變化。

Master主要負責以下工作:為tablet伺服器分配tablets,檢測新加入的或者過期失效的table伺服器、平衡tablet 伺服器的負載、以及對GFS中的檔案進行垃圾收集。除此之外,它還處理模式修改操作,例如建立表和列族。

每個Tablet伺服器都管理一組tablet(通常每個tablet伺服器有大約數十個至上千個tablet)。tablet伺服器處理它所載入的tablet的讀寫操作,以及分割增長的過大的tablet

和很多單主節點(Single-Master)型別的分散式儲存系統【17.21】類似,客戶資料都不經過master伺服器:客戶程式直接和tablet伺服器通訊來進行讀寫操作。由於BigTable的客戶程式不依賴master伺服器來獲取tablet的位置資訊,大多數客戶程式甚至完全不和master通訊。因此,在實際應用中master的負載是很輕的。

一個BigTable叢集儲存了很多表,每個表包含了一組tablet,而每個tablet包含了某個範圍內的行的所有相關資料。初始狀態下,每個表只有一個tablet組成。隨著表中資料的增長,它被自動分割成多個tablet,預設情況下每個tablet的大小大約是100MB200MB

5.1 Tablet的位置資訊

我們使用一個三層的、類似於B+[10]的結構儲存tablet的位置資訊(如圖4)

第一層是一個儲存在Chubby中的檔案,它包含了root tablet的位置資訊。root tablet在一個特殊的元資料(METADATA)表包含了裡所有的tablet的位置資訊。每一個元資料tablet包含了一組使用者tablet的的位置資訊。root tablet實際上只是元資料表的第一個tablet,只不過對它的處理比較特殊—root tablet永遠不會被分割—這就保證了tablet的位置層次不會超過三層。

元資料表將每個tablet的位置資訊儲存在一個行關鍵字下,而這個行關鍵字是由tablet所在的表的識別符號和tablet的最後一行編碼而成的。每一個元資料行在記憶體中大約儲存了1KB資料。在一個大小適中的、大小限制為128MB的元資料 tablet中,我們的三層結構位置資訊模式足夠定址234(三層27+10*27+10)個tablet(或者說在128M的元資料中可以儲存261個位元組)。

客戶程式庫會快取tablet的位置資訊。如果客戶程式不知道一個tablet的位置資訊,或者發現它快取的地址資訊不正確,那麼客戶程式就遞迴移動到tablet位置層次;如果客戶端快取是空的,那麼定址演算法需要通過三次網路來回通訊定址,這其中包括了一次Chubby讀操作。如果客戶端快取的地址資訊過期了,那麼定址演算法可能進行多達6次(alex注:其中的三次通訊發現快取過期,另外三次更新快取資料)網路來回通訊,因為過期快取條目只有在沒有查到資料(upon misses)的時候才能發現 (假設元資料tablet沒有被頻繁的移動)。儘管tablet的位置資訊是存放在記憶體裡的,所以不需訪問GFS,但是,通常我們會通過預取tablet地址來進一步的減少訪問開銷:無論何時讀取元資料表,都會為不止一個tablet讀取元資料。

在元資料表中還儲存了次級資訊(alex注:secondary information),包括與tablet有關的所有事件日誌(例如,什麼時候一個伺服器開始為該tablet提供服務)。這些資訊有助於排除故障和效能分析。

5.2 Tablet分配

每個tablet一次分配給一個tablet伺服器。master伺服器記錄活躍的tablet伺服器、當前tablettablet伺服器的分配、包括哪些tablet還沒有被分配。當一個tablet還沒有被分配、並且有一個tablet伺服器有足夠的空閒空間來裝載該tablet並且可用,master通過給這個tablet伺服器傳送一個tablet裝載請求分配該tablet

BigTable使用Chubby跟蹤記錄tablet伺服器。當一個tablet伺服器啟動時,它在一個指定的Chubby目錄下建立一個有唯一名字的檔案,並且獲取該檔案的獨佔鎖。master監控著這個目錄(伺服器目錄)y以便範閒tablet伺服器。如果tablet伺服器失去了Chubby上的獨佔鎖—比如由於網路斷開導致tablet伺服器丟失Chubby會話—它就停止對tablet提供服務。(Chubby提供了一種高效的機制,利用這種機制,tablet伺服器能夠在不招致網路擁堵的情況下檢查其是否還持有該鎖)。只要該檔案還存在,tablet伺服器就會試圖重新獲得對該獨佔鎖;如果檔案不存在了,那麼tablet伺服器就永遠不能再提供服務了,它會自行退出(so it kills itself)。只要tablet 伺服器終止(比如,叢集的管理系統將該tablet伺服器的主機從叢集中移除),它會嘗試釋放它持有的鎖,以便master儘快重新分配它的tablet

Master負責探測一個tablet伺服器何時不再為它的tablet提供服務,並且儘快重新分配那些tabletmaster通過輪詢tablet伺服器鎖的狀態來探測tablet伺服器何時不再為tablet提供服務。如果一個tablet伺服器報告它丟失了鎖,或者master最近幾次嘗試都無法和該伺服器通訊,master就會嘗試獲取該tablet伺服器檔案的獨佔鎖;如果master能夠獲取獨佔鎖,那麼就說明Chubby是正常執行的,而tablet 伺服器要麼是宕機了、要麼是不能和Chubby通訊了,因此,為了保證該tablet伺服器不能再提供服,master就刪除該tablet伺服器在Chubby上的伺服器檔案。一旦伺服器檔案被刪除了,master就把之前分配給該伺服器的所有的tablet放入未分配的tablet集合中。為了確保Bigtable叢集面對masterChubby之間網路問題不那麼脆弱,master在它的Chubby會話過期時會主動退出。但是不管怎樣,如上所述,master的故障不會改變現有tablettablet伺服器的分配。

當叢集管理系統啟動了一個master之後,master首先要了解當前tablet的分配狀態,之後才能夠修改它們。master在啟動的時候執行以下步驟:(1masterChubby中獲取一個唯一的master鎖,用來阻止併發的master例項;(2master掃描Chubby的伺服器目錄,獲取尋找正在執行的伺服器;(3master和每一個正在執行的tablet伺服器通訊,搜尋哪些tablet已經分配到了tablet伺服器中;(4master伺服器掃描元資料表獲取tablet的集合。只要掃描發現了一個還沒有分配的tabletmaster就將這個tablet加入未分配的tablet 集合,該集合使該talbet有機會參與talbet分配。

有一種複雜情況是:元資料tablet還沒有被分配之前是不能夠掃描它的。因此,在開始掃描之前(步驟4),如果在第三步中沒有發現對root tablet的分配,master就把root tablet加入到未分配的tablet集合中。這個附加操作確保了root tablet會被分配。由於root tablet包括了所有元資料tablet的名字,master在掃描完root tablet以後才瞭解所有元資料資訊。

現存tablet的集合只有在以下事件發生時才會改變:建立了一個新表或者刪除了一箇舊表、兩個現存tablet合併組成一個大的tablet、或者一個現存tablet被分割成兩個小的tabletmaster可以跟蹤這些改變,因為除了最後一個事件外的兩個事件都是由它初始化的。tablet分割事件需要特殊處理,因為它是由tablet伺服器初始化的。tablet伺服器通過在元資料表中為新的tablet記錄資訊的方式提交分割操作。在分割操作提交之後tablet伺服器會通知master。假如分割操作通知丟失(tablet伺服器或者master宕機),master在請求tablet伺服器裝載已經被分割的tablet的時候會探測到一個新的tablet。由於在元資料tablet中發現的tablet條目只是列舉了master請求載入的tablet的一部分,tablet伺服器會通知master分割資訊。

5.3 Tablet服務

如圖5所示,tablet的持久化狀態資訊儲存在GFS上。更新操作提交到儲存撤銷(REDO)記錄的提交日誌中。在這些更新操作中,最近提交的那些存放在一個叫做memtable的排序的緩衝區中;較早的更新存放在一系列SSTable中。為了恢復一個tablettablet伺服器在元資料表中讀取它的元資料。這些元資料包含組成一個tabletSSTable列表和一組還原點(redo points),這些點是指向包含tablet資料的任一提交日誌的指標。tablet伺服器把SSTable的索引讀進記憶體,之後通過應用還原點之後提交的所有更新來重構memtable

當寫操作到達tablet伺服器時,tablet伺服器首先要檢查這個操作格式是否正確、傳送者是否有執行這個改變的許可權。許可權驗證是通過從一個Chubby檔案裡讀取具有寫許可權的操作者列表來進行的(這個檔案幾乎總會在Chubby客戶快取裡命中)。有效的修改操作會記錄在提交日誌裡。可以採用組提交方式(alex注:group commit)來提高大量小的修改操作的吞吐量【1316】。當一個寫操作提交後,它的內容被插入到memtable裡面。

當讀操作到達tablet伺服器時,它同樣會檢查良構性和適當的許可權。一個有效的讀操作在一個由一系列SSTablememtable合併的視圖裡執行。由於SSTablememtable是按字典排序的資料結構,因此可以高效生成合並檢視。

當進行tablet的合併和分割時,引入(incoming)的讀寫操作能夠繼續進行。

5.4 Compactions

(alex注:這個詞挺簡單,但是在這節裡面挺難翻譯的。應該是空間縮減的意思,但是似乎又不能完全概括它在上下文中的意思,乾脆,不翻譯了)

隨著寫操作的執行,memtable的大小不斷增加。當memtable的尺寸到達一個臨界值的時候,這個memtable就會被凍結,然後建立一個新的memtable;被凍結住memtable會被轉換成SSTable並寫入GFSalex注:我們稱這種Compaction行為為Minor Compaction)。Minor Compaction過程有兩個目的:一是收縮tablet伺服器記憶體使用,二是在伺服器災難恢復過程中,減少必須從提交日誌裡讀取的資料量。在Compaction過程中,引入(incoming)的讀寫操作仍能繼續。

每一次Minor Compaction都會建立一個新的SSTable。如果這個行為未經檢查地持續下去,讀操作可能需要合併來任意個SSTable的更新;反之,我們通過定期在後臺執行Merging Compaction 過程限制這類檔案(shijinSStable)的數量。Merging Compaction過程讀取一些SSTablememtable的內容,輸出一個新的SSTable。只要Merging Compaction過程完成了,作為輸入的SSTablememtable就可以丟棄了。

重寫所有的SSTable到一個新的SSTableMerging Compaction過程叫作Major Compaction。由非Major Compaction產生的SSTable可以包含特殊的刪除條目,這些刪除條目能夠禁止仍然可用的較早SSTable中已刪除的資料(STables produced by non-major compactions can contain special deletion  entries that suppres s deleted data in older SSTables that are still live)。另一方面,Major Compaction過程生成的SSTable不包含已經刪除的資訊或資料。Bigtable迴圈掃描它所有的tablet並且定期對它們應用Major CompactionMajor Compaction機制允許Bigtable回收已經刪除的資料使用的資源,並且確保已刪除的資料及時從系統內消失(alex注:實際是回收資源。資料刪除後,它佔有的空間並不能馬上重複利用;只有空間回收後才能重複使用),這對儲存敏感資料的服務是非常重要的。

優化

上一節描述的實現需要很多優化來達到使用者要求的高效能、高可用性和高可靠性的目標。為了突出這些優化,本節描述了部分實現的詳細細節。

區域性性群組

客戶程式可以將多個列族組合成一個區域性性群族。對每個tablet中的每個區域性性群組都會生成一個單獨的SSTable。將通常不會一起訪問的列族分割成單獨的區域性性群組使讀取操作更高效。例如,在Webtable表中,網頁的元資料(比如語言和檢驗和Checksum)可以在一個區域性性群組中,網頁的內容可以在不同的群組:要讀取網頁元資料的應用程式沒有必要讀取整個頁面內容。

此外,可以以區域性性群組為單位指定一些有用的調整引數。比如,可以把一個區域性性群組設定為全部儲存在記憶體中。設定為存入記憶體的區域性性群組的SSTable依照惰性載入的策略裝載進tablet伺服器記憶體。載入完成之後,屬於該區域性性群組的列族的不用訪問硬碟即可讀取。這個特性對於需要頻繁訪問的小塊資料特別有用:在Bigtable內部,我們利用這個特性進行元資料表內的列族定位(for the location column famil