在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-行記錄結構
/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 (bytes.equals(tablename, root_table_name))
return
this.rootregionlocation;
} } else
if (bytes.equals(tablename, meta_table_name)) else
}
這是乙個遞迴呼叫的過程:
獲取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變更表名以及meta表修復
表名變更 1.停止表繼續插入 hbase shell disable tablename 2。製作快照 hbase shell snapshot tablename tablesnapshot 3.轉殖快照為新的名字 hbase shell clone snapshot tablesnapshot ...
literal和meta的意義和用法
literal 也就是普通純文字,對shell 來說沒特殊功能。meta 對shell 來說,具有特定功能的特殊保留字元。註一 關於bash shell 在處理command line 時的順序說明,請參考o reilly 出版社之learning the bash shell,2nd editio...
unity中的meta和mainfest檔案
meta和mainfest都是記錄資源資訊的檔案 其中meta是用於資源版本管理,匯入資源的時候,unity會會為每個資源自動生成乙個meta檔案,記錄這該資源的guid和一些資源引用資訊,但是同樣的資源,在不同的電腦上生成的meta檔案是不一樣的,那如果在多人開發中,你上傳了meta的資源,別人用...