hbase的rowkey該怎麼設計

網上查了很多資料,關於hbase rowkey到底應該怎麼設計。總結下來就是4點。

1.唯一原則。
必須在設計上保證其唯一性。由於在HBase中數據存儲是Key-Value形式,若HBase中同一表插入相同Rowkey,
則原先的數據會被覆蓋掉(如果表的version設置爲1的話),所以務必保證Rowkey的唯一性。

2.排序原則。
HBase的Rowkey是按照ASCII有序設計的,我們在設計Rowkey時要充分利用這點

3.散列原則。
設計的Rowkey應均勻的分佈在各個HBase節點上。拿常見的時間戳舉例,如果Rowkey是按系統時間戳的方式遞增,
Rowkey的第一部分如果是時間戳信息的話將造成所有新數據都在一個RegionServer上堆積的熱點現象,也就是通常說的Region熱點問題。
熱點發生在大量的client直接訪問集中在個別RegionServer上(訪問可能是讀,寫或者其他操作),
導致單個RegionServer機器自身負載過高,引起性能下降甚至Region不可用。

解決散列的方法包括:反轉,加鹽,hash散列。

4.長度原則。
Rowkey是一個二進制,Rowkey的長度被很多開發者建議說設計在10~100個字節,建議是越短越好。


看完這4點後都能明白rowkey該怎麼設計了,但是當你真正設計時又不知所措,我現在結合具體的一個業務場景來說說rowkey是怎麼設計的。

業務需求:實現一個類似百度雲盤的存儲系統。
1.有非常多的文件和文件夾需要存儲,以圖片、文檔爲主。
2.能快速查找到某個所需要的文件。
3.需要查找某個時間段內的所有文件。

-------------------------------------------------------

放在關係型數據庫中設計如下:
列名        註釋
Id            表主鍵
Name        目錄名稱
ParentId    父目錄Id,根目錄Id爲0
IsFile        true爲文件,false爲文件夾
createor    文件創建者
size        文件大小
type        文件類型

----------------------------------------

如果轉化爲hbase數據庫表如下:

Rowkey        Column

rowkey_id    cf:name
                    cf:parentId
                    cf:isFile
                    cf:createor
                    cf:size
                    cf:type
------------------------------------------------------


上面的表設計好了,現在如果想查找a.txt的文件夾怎麼辦?只通過查找rowkey_id根本做不到,難道掃描全表列族嗎,這是不現實的,所以需要改進。
改進後的表如下:
Rowkey      Column
name          cf:parentId
                   cf:isFile
                   cf:createor
                   cf:size
                   cf:type

------------------------------------------------------

這裏出現了新問題,如果有兩個叫a.txt的文件怎麼辦?不滿足rowkey的唯一性原則。繼續改進。
繼續改進:
Rowkey        Column
fullpath    cf:parentId
               cf:isFile
               cf:createor
               cf:size
               cf:type

------------------------------------------------------

現在基本滿足需求了,可是如果在某個目錄比如/home下面存儲着大量的文件,大量客戶端短時間內的請求操作又會造成熱點問題。
改進如下,設計兩張表,分別是目錄表和文件表。

目錄表只存儲目錄,rowkey存儲的是全路徑,列族sub存儲的是子目錄名稱,單純賦值爲1,無實際意義,
cf列族包括目錄創建者,以及當前目錄的唯一id。

Rowkey                Column
/dir1                     sub:dir2=1    sub:dir3=1
                            cf:createor=tom    cf:id=0001
/dir1/dir2              sub:dir4=1
                            cf:createor=tom cf:id=0002
/dir1/dir2/dir4       sub:dir5=1
                            cf:createor=tom cf:id=0003
                    
文件表:rowkey是目錄表中的唯一id+文件名的組合,c列族是內容的字節數組,cf列族包括文件創建者,文件大小和文件類型。
Rowkey                Column
0001_file1            c:content=bytes
                            cf:createor=mary cf:size cf:type
0002_file2            c:content=bytes
                            cf:createor=mary cf:size cf:type
0003_file3            c:content=bytes
                            cf:createor=mary cf:size cf:type
 ------------------------------------------------------


上述的設計解決了部分熱點問題,id+name的組合保證文件表大概是均勻分佈的,而且rowkey是有序的方便查找。而且根據rowkey可以進行目錄下的文件進行前綴過濾。

到這裏基本上就可以了,但是我們還可以繼續優化如下:
目錄表去掉了唯一id,改進了sub列族,如果是目錄,以d_dir命名,如果是文件,以f_file命名,賦值爲隨機的uuid
Rowkey                Column
/dir1                      sub:d_dir2=1    sub:f_file1=uuid
                             cf:createor=tom
/dir1/dir2               sub:dir4=1    sub:f_file2=uuid
                             cf:createor=tom
/dir1/dir2/dir4        sub:dir5=1    sub:f_file3=uuid
                             cf:createor=tom
                    
文件表的rowkey設計成了隨機的uuid
Rowkey                Column
uuid              c:content=bytes
                     cf:createor=mary cf:size cf:type
uuid              c:content=bytes
                     cf:createor=mary cf:size cf:type
uuid              c:content=bytes
                     cf:createor=mary cf:size cf:type

uuid的設計保證了文件表是均勻分佈的,而且比剛纔的好處是當你只想知道某個文件夾下所有目錄以及文件名稱還不想知道文件具體內容的時候直接查詢目錄表就行了,
不用再查詢一次文件表。不過壞處就是文件表不支持過濾查詢了。

以上就是rowkey的一種設計思路,希望能給大家一定啓發。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章