緣起:BigTable

Google的三篇論文,Google File SystemMapReduce以及Big Table能夠說是整個大數據領域的三駕馬車,這裏,咱們簡單介紹下這三駕馬車基本都是幹哈的,重點解讀下Bigtable: A Distributed Storage System for Structured Datac++

2003年的GFS:GFS是一個可擴展的分佈式文件系統,主要解決傳統單機文件系統中磁盤小,數據存儲無冗餘等問題;web

2004年的MapReduce:MapReduce是一個基於分佈式文件系統(例如,GFS)的分佈式計算框架,主要用來處理大規模數據集;算法

2006年的BigTable:BigTable是一個用來管理結構化數據的分佈式存儲系統,其本質上一個分佈式KV存儲系統。shell

BigTable是個啥?

BigTable是Google內部用來管理結構化數據的分佈式存儲系統,BigTable能夠輕易地擴展到上千臺機器,BigTable具備如下優勢:數據庫

  1. 適用場景普遍:從須要高吞吐量的批處理做業到低延遲的用戶數據服務,BigTable均可以勝任。
  2. 可伸縮:集羣規模可水平擴展,BigTable部署規模能夠小到3~5臺,大到數千臺,從而支撐不一樣的數據量;
  3. 高性能:性能這個,想必不用我BB了吧,各位看官,大家怎麼看呢?
  4. 高可用:BigTable是主從結構,不會產生單點故障;底層是GFS,數據冗餘備份;這還不具備高可用嘛???

與關係型數據庫不一樣,BigTable並不支持完整的關係數據模型,也就是說,BigTable是一個NoSQL數據庫,BigTable爲用戶提供了一個簡單的數據模型,該模型主要有如下兩個特色:api

  1. 客戶端能夠對數據的佈局和格式動態控制;這點與關係型數據庫有很大的差異,關係型數據庫中,表建立完成後,表中存儲的數據格式基本就固定了,列的數量及格式都沒法再改變了,BigTable則不一樣,BigTable的列能夠動態增長,徹底由客戶端控制。
  2. 客戶端能夠推理底層數據存儲系統中表示的數據的局部屬性(有點不太理解)。

BigTable中的數據是經過行(row)和列(column)進行索引的,行和列能夠是任意字符串。數組

客戶端能夠將各類形式的結構化和半結構數據序列化字符串,但BigTable只是將數據(Data)看作是未解釋字符串(字節數組)進行處理。緩存

客戶端能夠經過模式(Schema)參數來控制底層數據存儲的位置,BigTable的模式參數容許客戶端動態控制是從內存仍是磁盤提供數據。服務器

BigTable數據模型

讓咱們先來看看BigTable論文中是如何對BigTable定義的吧~網絡

A BigTable is a Sparse, Distributed, Persistent Multi-Dimensional Sorted Map. The Map is indexed by a row key, column key, and a timestamp; each value in the map is an uninterpreted array of bytes.

BigTable是一個Map,即Key/Value鍵值對,這個Map有啥特色呢?稀疏的,分佈式的,持久化存儲的且多維度排序的。

對於Map數據結構來講,最經常使用的操做就是經過Key檢索Value,BigTable中的Value是經過行,列,時間戳進行索引的。

# BigTable/Map的索引結構
(row:string, column:string, time:int64) ==> string

上圖是爲Web頁面建立的BigTable表Webtable

  1. row爲url地址的逆序;
  2. 列族contents用來存儲Web頁面內容;
  3. 列族anchor中存儲Web頁面中任何引用其餘頁面的錨點鏈接;

注意:BigTable中,每一個Cell都有多個Version,每一個Version對應一個時間戳。

Row Key

BigTable中的row key能夠是任意字符串(大部分場景下,用戶使用的row key大小爲10-100字節,但BigTable當前分配大小爲64KB)。

客戶端每次讀取/寫入數據時,指定row key時,不管有多少列同時被讀取/寫入,該讀寫操做都是原子操做的。

BigTable底層是按row key的字典順序存儲的,給定BigTable表,其row key range是動態分區的,每一個分區稱爲一個Tablet

Tips:較小範圍的row key數據讀取會更高效,緣由在於,這些數據讀取時,只須要與不多的機器通訊便可,效率較高。

Tips:客戶端能夠充分利用上述屬性,從而加快其數據訪問,獲取更高的吞吐量。例如,在Webtable中,使用url的逆序做爲row key,這樣作的好處是,訪問同一網站的頁面時,這些頁面一般會對應同一臺機器,不須要與集羣中多個節點通訊,讀取效率更高。

Column Families

多個Column Key構成的集合稱爲列族Column FamiliesColumn Key是最基本的訪問控制單元。

同一列族中的數據一般具備相同的數據類型(通常狀況下,同一列族的數據會放在一塊兒進行壓縮存儲)。

數據以列族(Column Families**)中某個列(**Column Key`)進行存儲以前,必須先建立該列族才行。

Tips:一般狀況下,一張BitTable表的列族得數量可能比較小(最多幾百個),並且在使用過程當中,列族一般是不變的,相反的,每一個表能夠擁有無數個列,也就是說,每一個列族均可以擁有無數個列,並且列是不須要提早定義的。

Column Key一般使用語法family:qualifier進行命名,列族必須由可打印字符構成,而列名能夠由任意字符構成。

Timestamps

BigTable表中每一個Cell包含同一數據的多個版本,這些版本經過時間戳進行索引,BigTable中的時間戳是64位整數。

時間戳能夠由服務端生成,也能夠由客戶端生成,須要避免衝突的應用程序必須由自身生成相應的時間戳。

不一樣版本的Cell以時間戳降序的方式進行存儲,以致於時間戳最近的版本最早會讀取到。

爲了不Cell的數據版本過多,提供列族級別的配置項,以便BigTable自動刪除舊的數據版本,一種是隻保留最近的幾個版本,另外一種是隻保留足夠新的版本數據(例如,保留最近7天寫入的數據版本)。

BigTable API

BigTable API提供建立/刪除表和列族的方法。

BigTable API提供修改集羣,表,列族元數據方法,例如,修改訪問控制權限等。

客戶端應用程序能夠執行寫入/刪除BigTable中的值,根據row key查詢值,迭表明中部分數據集等操做。

// Open the table
Table *t = OpenOrDie("/bigtable/web/wetable");
// 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;
// 應用原子操做到Webtable中的r1上
Apply(&op, &r1);

客戶端能夠在多個列族上進行迭代操做,同時,BigTable提供了幾種row, columns, timestamps構建方法來生成Scan實例。

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());
}

另外,BigTable支持其餘更復雜地操做數據的方式:

  1. 支持單行(single-row)事務,能夠實現給定row key時執行原子性的讀-改-寫操做。
  2. BigTable提供了批量接口,但不支持多行的事務操做。
  3. BigTable容許將Cell用做整數計數器。
  4. BigTable支持在服務端地址空間內執行客戶端腳本,該腳本爲Sawzall語言(懵逼)。

BigTable構建基礎

BigTable是基於Google的一些基礎組件構建而成的。

BigTable使用GFS(Google File System)來存儲日誌(log)和數據(data)文件。

BigTable集羣一般運行在一個共享的服務器集羣中,BigTable的進程一般與其餘分佈式應用程序進程共享同一臺服務器。

BigTable依賴集羣管理系統來實現做業調度,管理共享機器上的資源,處理機器故障以及監視機器狀態。

BigTable使用Google SSTable文件格式來存儲內部數據,SSTable提供了從keysvalues的持久化的,順序的,不可變的映射,另外,SSTable中keys和values均是任意字節數組,另外,SSTable提供了根據key檢索value以及根據key範圍檢索Value的功能。

SSTable由不少Block(每一個Block默認大小爲64KB,可配置的)組成,Block Index(存儲在Block尾部)用來定位Blocks,當客戶端打開SSTable時,會將Block Index加載到內存的。

SSTable中檢索指定keyvalues時能夠經過Single Disk Seek實現:

​ 首先加載Block Index到內存中,而後經過二分檢索到key所在的Block,最後將磁盤中合適的Block加載到內存檢索便可。

BigTable依賴高可用且可持久化的分佈式鎖服務Chubby,Chubby服務包含4個活躍的副本(節點),其中一個節點選舉爲Master並處理用戶請求,當大多數副本副本正常運行且能夠互相通訊時,Chubby被認爲是正常運行的。Chubby使用Paxos算法實現副本數據一致。

Chubby提供了包含目錄和小文件的命名空間,每一個目錄或文件能夠當成一個鎖來使用,讀取和寫入文件時原子操做。

Chubby客戶端會同步緩存Chubby文件,每一個Chubby客戶端會自動維護一個與Chubby服務的會話,在會話到期時,若是客戶端沒法經過Chubby服務更新到期時間,則會話會被中斷,會話到期時,客戶端會丟失全部全部鎖且沒法執行open操做。

Chubby客戶端能夠在Chubby文件/目錄上註冊回調方法,當會話到期或文件/目錄改變是回調該方法。

BigTable使用Chubby完成各類各樣的任務:

  1. 保證集羣內同時最多存在一個Master節點。
  2. 存儲BigTable表數據的啓動位置。
  3. 發現Tablet服務以及檢測Tablet是否存活。
  4. 存儲BigTable表Schema信息(每張表的列族信息)。
  5. 存儲訪問控制列表。

BigTable實現原理

BigTable實現主要包括三部分:

  1. 客戶端須要使用的庫
  2. 一個Master Server
    1. 分配Tablet到哪一個Tablet Server上;
    2. 檢測是否有Tablet Server新增或到期;
    3. Tablet Server負載均衡;
    4. GFS上垃圾文件回收;
    5. 處理BigTable表Schema修改(例如,建立/新增表列族);
  3. 多個Tablet Server:
    1. 每一個Tablet Server維護一個Tablet集合(每一個Tablet Server一般能夠維護10到1000個Tablet);
    2. 處理其負責的Tablet的讀寫請求,在Tablet太大時,負責Tablet的分裂;
    3. 根據集羣負載狀況,Tablet Server能夠動態添加或移除。

Tips:與其餘單Master分佈式存儲系統相似,客戶端數據不會路由到Master,而是直接與Tablet Server通訊,進而實現數據的讀寫。

Tips:不少BigTable客戶端不須要依賴於Master定位Tablet信息,也就是說,大部分場景下客戶端不須要與Master通訊。

Tablet定位模型

BigTable使用相似B+樹的三層結構來存儲Tablet位置信息。

第一層:一個Chubby文件,該文件存儲了root tablet的位置信息,因爲該文件是Chubby文件,也就意味着,一旦Chubby服務不可用,整個BigTable就丟失了root tablet的位置,整個服務也就不可用了。

第二層:root tabletroot tablet其實就是元數據表METADATA Table的第一個Tablet,該Tablet中保存着元數據表其餘Tablet的位置信息,root tablet很特殊,爲了保證整個樹的深度不變,root tablet從不分裂。

注意:對於元數據表METADATA Table來講,除了第一個特殊的Tablet來講,其他每一個Tablet包含一組用戶Tablet位置信息集合。

注意:METADATA Table存儲Tablet位置信息時,Row Key是經過對Tablet Table Identifier和該Tablet的End Row生成的。

注意:每一個METADATA TableRow Key大約佔用1KB的內存,通常狀況下,配置METADATA Table的大小限制爲128MB,也就是說,三層的定位模式大約能夠尋址2^34個Tablets。

第三層:其餘元數據表的Tablet,這些Tablet與root tablet共同構成整個元數據表。注意:元數據表雖然特殊,但仍然服從前面介紹的數據模型,每一個Tablet也由專門的Tablet Server負責,這就是爲何不須要Master Server提供位置信息的緣由,客戶端會緩存Tablet的位置信息,若是在緩存中找不到指定Tablet的位置信息,則須要查詢該三層結構了,一次訪問Chubby服務,兩次Tablet Server訪問。

Tablet分配模型

每一個Tablet只能分配給某個Tablet Server。

Master Server維護當前哪些Tablet Server是活躍的,哪些Tablet分配給了哪些Tablet Server,哪些Tablet還未分配,當某個Tablet還未被分配、且恰好存在Tablet Server有足夠的空間裝載該Tablet時,Master Server會向該Tablet Server發送裝載請求。

BigTable使用Chubby服務來檢測Tablet Server是否存活,當Tablet Server啓動時,會在特定的Chubby目錄下建立排它鎖,BigTable會監控該目錄來發現哪些Tablet Server存活,當Tablet Server丟失其排它鎖時(例如,網絡緣由致使Tablet Server丟失Chubby會話)。

Chubby服務提供了很是高效地檢測會話是否持有鎖的機制,且不會致使網絡擁塞。

當Tablet Server的排它鎖文件存在時,Tablet Server可能會從新獲取該鎖,也就是,該鎖是可重入的;排它鎖文件不存在,則Tablet Server不會再次請求該鎖,而是自殺。

Tablet Server進程終止是,會嘗試釋放鎖,以便Master Server能夠儘快地將其維護的Tablet分配到其餘節點上。

Master負責檢測Tablet Server是否還在爲其餘Tablet提供服務,並儘快從新分配其負責的Tablet到其餘Tablet Server上。

問題是,Master是如何檢測的呢?

Master會按期向每一個Tablet Server詢問其鎖的狀態,若是Tablet Server向其報告鎖已丟失,或者Master最後幾回嘗試都沒法訪問服務器,則Master將嘗試獲取該Tablet Server對應的排他鎖文件,若是能夠獲取,則說明Chubby處於活躍狀態,而Tablet Server已死或者沒法訪問Chubby,Master能夠經過刪除其服務器文件來確保Tablet Server再也不提供服務。一旦Tablet Server對應的排它鎖文件被刪除後,Master Server能夠將先前分配給該Tablet SErver的全部Tablet移動到其餘未分配的Tablet Server中。

爲了確保Bigtablet集羣不受Master Server與Chubby服務之間網絡問題影響,若是Master的Chubbby會話到期,則Master會自動殺死本身,如上所述,Master Server設備故障不會更改Tablet分配到其餘Tablet Server上。

當Master Server啓動時,在其能夠修改Tablet分配以前,須要先感知到當前Tablet分佈才行,啓動流程以下:

  1. 獲取Chubby文件(排它鎖),阻止併發實例化Master
  2. Master會掃描Tablet Server排它鎖的Chubby文件目錄,拿到當前活躍Tablet Server信息
  3. Master與全部Tablet Server通訊獲取其所維護的Tablet信息
  4. Master會同時掃描METADATA表獲取Tablets集合,在掃描的過程當中,當Master發現了還未分配的Tablet時,Master將該Tablet加入未分配的Tablet集合等待合適的時機分配。

在第4不掃描METADATA表時可能會遇到一種複雜的狀況:METADATA表的Tablet還未分配以前是不可以掃描它的。

步驟3掃描過程當中,若是發現Root Tablet尚未分配,Master就把Root Tablet加入到未分配的Tablet集合。

上面這個附加操做確保了Root Tablet會被分配。Root Tablet包括了 全部METADATA的Tablet的名字,意味着Master掃描完Root Tablet後就獲得了全部METADATA表的Tablet的名字了。

現有的Tablet集合只有在建立新表或者刪除了舊錶、兩個 Tablet被合併了或Tablet被分割成兩個小的Tablet時纔會發生改變。

Master能夠跟蹤記錄全部這些事件, 除了Tablet分割外的事件都是Master發起的的。

Tablet分割事件須要特殊處理,由於該事件是由Tablet 服務器發起的。

Tablet分割結束後,Tablet Server經過在METADATA表添加Tablet的信息來提交這 個操做;分割結束後,Tablet Server會通知Master。

若是分割操信息已提交,卻沒有通知到Master(可能兩個服務器中有一個宕機了),Master在要求Tablet服務器裝載已經被分割 的子表的時候會發現一個新的Tablet。對比METADATA表中Tablet的信息,Tablet Server會發現 Master要求其裝載的Tablet並不完整,就會從新向Master發送通知信息,從而更新METADATA表。

Tablet Server

Tablet的數據持久化存儲在GFS中,具體持久化流程以下圖所示。

Updates操做會先提交到log(WAL)中,log主要用來進行數據恢復的。全部的Updates中,最近提交的那部分會存放在排序的緩存中,這個緩存稱爲MemTable,更早的Updates會存放在一系列SSTable中,這些SSTable本質上就是MemTablet刷盤生成的。

爲了恢復Tablet,Tablet Server首先從MEMTABLE中讀取元數據信息,元數據信息包含組成該Tablet的SSTable列表及一系列重啓點,這些重啓點指向包含該Tablet數據的已提交日誌記錄,Tablet Server會把SSTable的索引讀入內存,根據重啓點恢復MemTable。

Tablet Server接收到數據寫入請求時,Tablet Server首先要檢查操做格式是否正確、操做發起者是否有執行這個操做的權限。權限驗證的方法是根據從Chubby文件裏讀取出來的具備寫權限的操做者列表來進行驗證(這個文件幾乎必定會存放在Chubby客戶緩存裏)。成功的修改操做會記錄在提交日誌裏。能夠採用批量提交的方式來提升大量小的修改操做的應用程序的吞吐量。

數據寫如操做提交後,數據最終會被插入到MemTable裏。

Tablet Server接收到數據讀取請求時,Tablet Server會做相似的完整性和權限檢查。一個有效的讀操做在一個由一系列SSTable和memtable合併的視圖裏執行的。因爲SSTable和memtable是按字典排序的數據結構,所以能夠高效生成合並視圖。

Tablet合併和分割時,正在進行的讀寫操做可以繼續進行。

Compaction(合併)

隨着數據的不斷寫入,MemTable佔用的內存會不斷增長。當MemTable佔用的內存超過必定閾值時,內存中的MemTable會被凍結,切換爲只讀狀態,同時建立一個新的MemTable,新的數據寫入請求會寫入到新的MemTable中,只讀的MemTable會被轉換爲SSTable並最終寫入底層存儲系統(GFS)中,這個過程被稱做小合併(Minor Compaction)。

小合併的做用主要有兩個:

  1. 下降Tablet Server的內存使用
  2. 在Tablet Server意外宕機時,下降從WAL恢復MemTable時須要讀取的數據量。

每次小合併都會生成SSTable,若是隻有小合併,一直這麼持續下去,那麼,在Tablet Server接收到數據讀取操做時,就須要充全部可能存在待檢索row keySSTable檢索,而後合併全部更新操做,才能最終獲得最新的value值。

爲了不上述這種狀況發生,咱們在後臺週期性地執行大合併(Major Compaction),大合併會讀取幾個SSTable,而後進行數據合併,合併結束後,便可將原先的SSTable文件刪除。

優化及改進

前面一個章節描述了BigTable的底層實現原理,不過,爲了知足用戶所需的高性能,高可用和可靠性。在具體實現時須要各類優化才行。

Locality Groups

客戶端能夠將多個列族組成Locality Graph。每一個Tablet會爲Locality Group中的數據單獨生成SSTable。

將一般不會一切訪問的列族分離到單獨的Locality Group中,能夠實現更高效的數據讀取。

例如,能夠將Webtable中的頁面元數據(例如,語言和檢驗和)放在同一Locality Group中,葉綿綿的內容在不一樣組中,當應用程序想要讀取頁面的元數據信息時,不須要讀取全部的頁面內容便可完成。

此外,還能夠針對每一個Locality Grou作相應的參數優化,例如,能夠聲明將某個Locality Group放到內存中。

內存中Locality Group對應的SSTable會被延遲加載到Tablet Server中,一旦加載完成,在不訪問磁盤的狀況下,實現Locality Group數據訪問,此功能對於頻繁訪問的小塊數據十分有用,Google內部用來存儲元數據表。

Compression(壓縮)

客戶端能夠控制是否壓縮Locality Group的SSTables以及使用哪一種方式進行壓縮。

用戶指定的壓縮格式應用於每一個SSTable Block(其大小可經過特定於局部性組的調整參數進行控制)。

經過單獨壓縮每一個塊會損失一些空間,但好處是能夠讀取SSTable的小部分,而無需對整個文件進行解壓縮。

許多客戶端使用兩遍自定義壓縮方案。第一遍壓縮過程使用了Bentley和McIlroy的方案[6],在一個大範圍內使用前綴壓縮算法對普通的長字符串進行壓縮。第二遍壓縮使用了一個快速壓縮算法,該算法在一個16kb的小窗口中尋找重複數據。兩種壓縮過程都很是快,現代機器上,它們的編碼速度爲100-200 MB/s,解碼速度爲400-1000 MB/s。儘管咱們在選擇壓縮算法時強調的是速度而不是空間縮減,但這種兩遍壓縮方案作得很是好。

Caching(緩存)

爲了提高數據讀取性能,Tablet Server使用兩級緩存。

Scan Cache是Higher-Level緩存,該緩存會緩存SSTablet接口返回的Key-Value鍵值對。

Block Cache是Lower-Level緩存,該緩存會緩存從GFS中讀取的SSTable Block。

Scan Cache對於須要頻繁訪問相同數據的應用程序來講是很是有用的。

Block Cache則對須要訪問臨近數據的應用程序來講很是有用。

Bloom Filters(布隆過濾器)

如上個章節中對BigTable底層實現原理描述的同樣,數據讀取操做最終是從Tablet的SSTable中讀取的。若是SSTable再也不內存中,最終就須要經過讀取磁盤來實現數據讀取了。經過爲特定Locality Group的SSTable建立布隆過濾器,能夠減小磁盤的訪問次數。

布隆過濾器使得咱們經過查詢布隆過濾器來判斷SSTable是否包含指定行/列的數據,對於某些應用程序,經過使用布隆過濾器能夠顯著下降Tablet Server的磁盤尋道次數。另外,使用布隆過濾器意味着對於不存在的行/列數據能夠避免大量沒必要要的磁盤讀取。

WAL(提交日誌實現)

若是未每一個Tablet都生成相應的WAL文件,那麼GFS就須要同時寫入不少文件,併發量很高,這種場景下,底層每一個GFS服務器爲了將日誌數據寫入不一樣的物理文件,會致使大量磁盤尋道,效率極低。此外,每一個Tablet提交單獨的日誌文件也會下降批量提交優化性能,緣由在與,因爲分Tablet進行提交,對應的批量數據就回比較少。爲了解決這些問題,咱們將每一個Talbet Server中全部的Tablet的數據寫入日誌追加到同一日誌文件中,從而下降GFS的併發量,也下降底層GFS的物理磁盤尋道。

每一個Tablet Server僅建立一個提交日誌(WAL)文件,在正常操做場景下,能夠大幅度提升性能,但數據恢復時卻很複雜。

一臺Tablet Server宕機時,其維護的全部Tablets將被轉移到其餘Tablet Server上,每臺Tablet Server僅會裝載少許原始Tablet Server的Tablet。爲了恢復Tablet Server的狀態,新的Tablet Server須要從原始Tablet寫入的提交日誌中從新應用該平板電腦的更新。然而,該宕機Tablet Server上的全部的Tablet的更新操做混合在同一個物理日誌文件中。

一種方法是讓每一個新的Tablet Server讀取完整的提交日誌文件,並只應用它須要恢復的Tablet所需的條目。然而,在這種方案下,若是當前集羣有100臺機器從一臺故障的Tablet Server上分別分配Tablet,那麼日誌文件將被讀取100次(每臺服務器一次)。

爲了不日誌的重複讀取,首先按照<table; row name; log sequence number>對提交日誌條目進行排序。在已排序的輸出中,特定Tablet的全部更新操做都是連續的,所以,可經過一次磁盤搜索和順序讀取有效地讀取。爲了並行排序,將日誌文件按64MB切分,在不一樣的Tablet Server上並行排序。排序過程由Master協調,並指示每臺Tablet Server須要從某些提交日誌文件中恢復更新日誌時啓動。

WAL日誌寫入GFS有時會因爲各類緣由致使性能中斷(例如,涉及寫操做的GFS服務器計算機,或爲到達三個GFS服務器的特定集合而穿越的網絡路徑遇到網絡擁塞或負載太重)。

爲了保護更新操做不受GFS延遲峯值的影響,每一個Tablet Server實際上有兩個日誌寫入線程,每一個線程都寫入本身的日誌文件;這兩個線程一次只有一個處於活動狀態。若是對WAL日誌文件的寫入執行得不好,則日誌文件寫入將切換到另外一個線程,提交日誌隊列中的更新操做將由新活動的日誌寫入線程寫入。日誌條目包含序列號,以便在恢復過程消除此日誌線程切換過程當中產生的重複條目。

加速Tablet恢復

若是Master將Tablet從一個Tablet Server移動到另外一個Tablet Server,則源Tablet Server首先對該Tablet Server進行一次小合併。這種合併經過減小Tablet Server提交日誌中未壓縮狀態的數量來縮短恢復時間。完成壓縮後,Tablet Server中止爲該Tablet提供服務。

在實際卸載Tablet以前,Tablet Server會執行另外一次(一般很是快速)小合併,以消除執行第一次小合併時到達的Tablet Server日誌中的任何剩餘未壓縮狀態。完成第二次小壓縮後,能夠將Tablet加載到另外一臺Tablet Server上,而無需恢復任何日誌條目。

總結

之因此寫這篇博客,其實,是爲了引出LevelDB,LevelDB又是啥呢?

LevelDB一個單機的開源的高效的KV存儲系統,該單機KV存儲系統,能夠說是高度復刻了BigTable中的Tablet,而BigTable畢竟不是開源噠,咱們經過Google的這篇論文,也只是能瞭解到BigTable的總體架構,可是具體細節就只能YY,或者去看HBase(參考BigTable實現的一個開源分佈式列式數據庫)的源碼了。

不過呢,出於工做須要呢,目前對HBase需求不大,更須要弄懂單機KV系統是如何實現的,因此呢,我就屁顛屁顛地區看LevelDB了,相比於BigTable/HBase,僅僅是單機和分佈式的區別了,並且,LevelDB代碼量更小,更容易學習和掌控,接下來,我會經過一系列筆記來記錄和分享本身學習LevelDB設計原理及底層細節的過程,但願你們多多關注呀。

歡迎關注個人我的公衆號,博客會同步更新喲~

相關文章
相關標籤/搜索