HBase -ROOT-和.META.表結構
在HBase中,大部分的操作都是在RegionServer完成的,Client端想要插入,刪除,查詢資料都需要先找到相應的RegionServer。什麼叫相應的RegionServer?就是管理你要操作的那個Region的RegionServer。Client本身並不知道哪個RegionServer管理哪個Region,那麼它是如何找到相應的RegionServer的?本文就是在研究原始碼的基礎上揭祕這個過程。
在前面的文章“HBase儲存架構”中我們已經討論了HBase基本的儲存架構。在此基礎上我們引入兩個特殊的概念:-ROOT-和.META.。這是什麼?它們是HBase的兩張內建表,從儲存結構和操作方法的角度來說,它們和其他HBase的表沒有任何區別,你可以認為這就是兩張普通的表,對於普通表的操作對它們都適用。它們與眾不同的地方是HBase用它們來存貯一個重要的系統資訊——Region的分佈情況以及每個Region的詳細資訊。
好了,既然我們前面說到-ROOT-和.META.可以被看作是兩張普通的表,那麼它們和其他表一樣就應該有自己的表結構。沒錯,它們有自己的表結構,並且這兩張表的表結構是相同的,在分析原始碼之後我將這個表結構大致的畫了出來:
-ROOT-和.META.表結構
我們來仔細分析一下這個結構,每條Row記錄了一個Region的資訊。
首先是RowKey,RowKey由三部分組成:TableName, StartKey 和 TimeStamp。RowKey儲存的內容我們又稱之為Region的Name。哦,還記得嗎?我們在前面的文章中提到的,用來存放Region的資料夾的名字是RegionName的Hash值,因為RegionName可能包含某些非法字元。現在你應該知道為什麼RegionName會包含非法字元了吧,因為StartKey是被允許包含任何值的。將組成RowKey的三個部分用逗號連線就構成了整個RowKey,這裡TimeStamp使用十進位制的數字字串來表示的。這裡有一個RowKey的例子:
Table1,RK10000,12345678
然後是表中最主要的Family:info,info裡面包含三個Column:regioninfo, server, serverstartcode。其中regioninfo就是Region的詳細資訊,包括StartKey, EndKey 以及每個Family的資訊等等。server儲存的就是管理這個Region的RegionServer的地址。
所以當Region被拆分、合併或者重新分配的時候,都需要來修改這張表的內容。
到目前為止我們已經學習了必須的背景知識,下面我們要正式開始介紹Client端尋找RegionServer的整個過程。我打算用一個假想的例子來學習這個過程,因此我先構建了假想的-ROOT-表和.META.表。
.META.行記錄結構
現在假設我們要從Table2裡面插尋一條RowKey是RK10000的資料。那麼我們應該遵循以下步驟:
從.META.表裡面查詢哪個Region包含這條資料。
獲取管理這個Region的RegionServer地址。
連線這個RegionServer, 查到這條資料。
好,我們先來第一步。問題是.META.也是一張普通的表,我們需要先知道哪個RegionServer管理了.META.表,怎麼辦?有一個方法,我們把管理.META.表的RegionServer的地址放到ZooKeeper上面不久行了,這樣大家都知道了誰在管理.META.。
貌似問題解決了,但對於這個例子我們遇到了一個新問題。因為Table1實在太大了,它的Region實在太多了,.META.為了儲存這些Region資訊,花費了大量的空間,自己也需要劃分成多個Region。這就意味著可能有多個RegionServer在管理.META.。怎麼辦?在ZooKeeper裡面儲存所有管理.META.的RegionServer地址讓Client自己去遍歷?HBase並不是這麼做的。
HBase的做法是用另外一個表來記錄.META.的Region資訊,就和.META.記錄使用者表的Region資訊一模一樣。這個表就是-ROOT-表。這也解釋了為什麼-ROOT-和.META.擁有相同的表結構,因為他們的原理是一模一樣的。
假設.META.表被分成了兩個Region,那麼-ROOT-的內容看上去大概是這個樣子的:
-ROOT-行記錄結構
這麼一來Client端就需要先去訪問-ROOT-表。所以需要知道管理-ROOT-表的RegionServer的地址。這個地址被存在ZooKeeper中。預設的路徑是:
/hbase/root-region-server
等等,如果-ROOT-表太大了,要被分成多個Region怎麼辦?嘿嘿,HBase認為-ROOT-表不會大到那個程度,因此-ROOT-只會有一個Region,這個Region的資訊也是被存在HBase內部的。
現在讓我們從頭來過,我們要查詢Table2中RowKey是RK10000的資料。整個路由過程的主要程式碼在org.apache.hadoop.hbase.client.HConnectionManager.TableServers中:
private HRegionLocation locateRegion(final byte[] tableName,
final byte[] row, boolean useCache) throws IOException {
if (tableName == null || tableName.length == 0) {
throw new IllegalArgumentException("table name cannot be null or zero length");
}
if (Bytes.equals(tableName, ROOT_TABLE_NAME)) {
synchronized (rootRegionLock) {
// This block guards against two threads trying to find the root
// region at the same time. One will go do the find while the
// second waits. The second thread will not do find.
if (!useCache || rootRegionLocation == null) {
this.rootRegionLocation = locateRootRegion();
}
return this.rootRegionLocation;
}
} else if (Bytes.equals(tableName, META_TABLE_NAME)) {
return locateRegionInMeta(ROOT_TABLE_NAME, tableName, row, useCache, metaRegionLock);
} else {
// Region not in the cache – have to go to the meta RS
return locateRegionInMeta(META_TABLE_NAME, tableName, row, useCache, userRegionLock);
}
}
這是一個遞迴呼叫的過程:
獲取Table2,RowKey為RK10000的RegionServer => 獲取.META.,
RowKey為Table2,RK10000, 99999999999999的RegionServer => 獲取-ROOT-,RowKey為.META.,
Table2,RK10000,99999999999999,99999999999999的RegionServer => 獲取-ROOT-的RegionServer => 從ZooKeeper得到-ROOT-的RegionServer => 從-ROOT-表中查到RowKey最接近(小於) .META.,
Table2,RK10000,99999999999999,99999999999999的一條Row,並得到.META.的RegionServer => 從.META.表中查到RowKey最接近(小於)Table2,RK10000, 99999999999999的一條Row,並得到Table2的RegionServer => 從Table2中查到RK10000的Row
到此為止Client完成了路由RegionServer的整個過程,在整個過程中使用了新增“99999999999999”字尾並查詢最接近(小於)RowKey的方法。對於這個方法大家可以仔細揣摩一下,並不是很難理解。
最後要提醒大家注意兩件事情:
1. 在整個路由過程中並沒有涉及到MasterServer,也就是說HBase日常的資料操作並不需要MasterServer,不會造成MasterServer的負擔。
2. Client端並不會每次資料操作都做這整個路由過程,很多資料都會被Cache起來。至於如何Cache,則不在本文的討論範圍之內。
相關文章
- HBase學習之Hbase的邏輯結構和物理結構
- HBase的表結構你設計得不對!
- HBase 的結構與表的對應關係
- Hbase架構和搭建架構
- HBase 資料儲存結構
- HBase 系統架構及資料結構架構資料結構
- 理解索引:HBase介紹和架構索引架構
- Hbase學習二:Hbase資料特點和架構特點架構
- 一文講清HBase儲存結構
- mysql複製表結構和資料MySql
- Hbase表設計
- 一文講清HBase的儲存結構
- mysql 如何複製表結構和資料MySql
- 複製表結構和資料SQL語句SQL
- HBase學習的第五天--HBase進階結尾和phoenix開頭
- clickhouse如何表結構
- hbase 的架構分析架構
- 深入HBase架構原理架構
- mysql完全複製一個表(結構和資料)MySql
- 資料結構和演算法-雜湊表 (HashTable)資料結構演算法
- flowable 表結構說明
- 表結構對比版本
- HBase2實戰:HBase Flink和Kafka整合Kafka
- HBase知識點總結
- Hbase問題小結(一)
- JavaScript資料結構——字典和雜湊表的實現JavaScript資料結構
- 《資料結構與演算法》——表、棧和佇列資料結構演算法佇列
- oracle中判斷欄位是否存在和新增表結構Oracle
- 資料結構練習題(順序表和單連結串列)C++資料結構C++
- 快速理解HBase和BigTable
- 資料結構 - 線性表 - 順序表資料結構
- PLSQL只匯出表結構SQL
- clickhouse表結構匯出為
- 如何設計SKU表結構
- [資料結構] - 線性表資料結構
- 資料結構——線性表資料結構
- 資料結構——雜湊表資料結構
- 資料結構 | 線性表資料結構
- 資料結構-線性表資料結構