Google的三篇論文,Google File System,MapReduce以及Big Table可以說是整個大資料領域的三駕馬車,這裡,我們簡單介紹下這三駕馬車基本都是幹哈的,重點解讀下Bigtable: A Distributed Storage System for Structured Data。
2003年的GFS:GFS是一個可擴充套件的分散式檔案系統,主要解決傳統單機檔案系統中磁碟小,資料儲存無冗餘等問題;
2004年的MapReduce:MapReduce是一個基於分散式檔案系統(例如,GFS)的分散式計算框架,主要用來處理大規模資料集;
2006年的BigTable:BigTable是一個用來管理結構化資料的分散式儲存系統,其本質上一個分散式KV儲存系統。
BigTable是個啥?
BigTable是Google內部用來管理結構化資料的分散式儲存系統,BigTable可以輕易地擴充套件到上千臺機器,BigTable具有以下優點:
- 適用場景廣泛:從需要高吞吐量的批處理作業到低延遲的使用者資料服務,BigTable都可以勝任。
- 可伸縮:叢集規模可水平擴充套件,BigTable部署規模可以小到3~5臺,大到數千臺,從而支撐不同的資料量;
- 高效能:效能這個,想必不用我BB了吧,各位看官,你們怎麼看呢?
- 高可用:BigTable是主從結構,不會產生單點故障;底層是GFS,資料冗餘備份;這還不具有高可用嘛???
與關係型資料庫不同,BigTable並不支援完整的關係資料模型,也就是說,BigTable是一個NoSQL資料庫,BigTable為使用者提供了一個簡單的資料模型,該模型主要有以下兩個特點:
- 客戶端可以對資料的佈局和格式動態控制;這點與關係型資料庫有很大的差別,關係型資料庫中,表建立完成後,表中儲存的資料格式基本就固定了,列的數量及格式都無法再改變了,BigTable則不同,BigTable的列可以動態增加,完全由客戶端控制。
- 客戶端可以推理底層資料儲存系統中表示的資料的區域性屬性(有點不太理解)。
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:
- row為url地址的逆序;
- 列族contents用來儲存Web頁面內容;
- 列族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 Families
,Column 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支援其他更復雜地運算元據的方式:
- 支援單行(single-row)事務,可以實現給定
row key
時執行原子性的讀-改-寫操作。 - BigTable提供了批量介面,但不支援多行的事務操作。
- BigTable允許將Cell用作整數計數器。
- BigTable支援在服務端地址空間內執行客戶端指令碼,該指令碼為
Sawzall
語言(懵逼)。
BigTable構建基礎
BigTable是基於Google的一些基礎元件構建而成的。
BigTable使用GFS(Google File System)來儲存日誌(log)和資料(data)檔案。
BigTable叢集通常執行在一個共享的伺服器叢集中,BigTable的程式通常與其他分散式應用程式程式共享同一臺伺服器。
BigTable依賴叢集管理系統來實現作業排程,管理共享機器上的資源,處理機器故障以及監視機器狀態。
BigTable使用Google SSTable
檔案格式來儲存內部資料,SSTable
提供了從keys
到values
的持久化的,順序的,不可變的對映,另外,SSTable
中keys和values均是任意位元組陣列,另外,SSTable
提供了根據key檢索value以及根據key範圍檢索Value的功能。
SSTable
由很多Block
(每個Block預設大小為64KB,可配置的)組成,Block Index
(儲存在Block尾部)用來定位Blocks,當客戶端開啟SSTable
時,會將Block Index
載入到記憶體的。
從SSTable
中檢索指定key
的values
時可以通過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完成各種各樣的任務:
- 保證叢集內同時最多存在一個Master節點。
- 儲存BigTable表資料的啟動位置。
- 發現Tablet服務以及檢測Tablet是否存活。
- 儲存BigTable表Schema資訊(每張表的列族資訊)。
- 儲存訪問控制列表。
BigTable實現原理
BigTable實現主要包括三部分:
- 客戶端需要使用的庫
- 一個Master Server
- 分配Tablet到哪個Tablet Server上;
- 檢測是否有Tablet Server新增或到期;
- Tablet Server負載均衡;
- GFS上垃圾檔案回收;
- 處理BigTable表Schema修改(例如,建立/新增表列族);
- 多個Tablet Server:
- 每個Tablet Server維護一個Tablet集合(每個Tablet Server通常可以維護10到1000個Tablet);
- 處理其負責的Tablet的讀寫請求,在Tablet太大時,負責Tablet的分裂;
- 根據叢集負載情況,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 tablet,root 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 Table
的Row 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分佈才行,啟動流程如下:
- 獲取Chubby檔案(排它鎖),阻止併發例項化Master
- Master會掃描Tablet Server排它鎖的Chubby檔案目錄,拿到當前活躍Tablet Server資訊
- Master與所有Tablet Server通訊獲取其所維護的Tablet資訊
- 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
)。
小合併的作用主要有兩個:
- 降低Tablet Server的記憶體使用
- 在Tablet Server意外當機時,降低從WAL恢復MemTable時需要讀取的資料量。
每次小合併都會生成SSTable
,如果只有小合併,一直這麼持續下去,那麼,在Tablet Server接收到資料讀取操作時,就需要充所有可能存在待檢索row key
的SSTable
檢索,然後合併所有更新操作,才能最終得到最新的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設計原理及底層細節的過程,希望大家多多關注呀。