Hbase 的RowKey設計原則

2021-09-23 07:35:26 字數 3715 閱讀 7697

hbase所謂的三維有序儲存的三維是指:rowkey(行主鍵),column key(columnfamily+qualifier),timestamp(時間戳)三部分組成的三維有序儲存。

rowkey是行的主鍵,而且hbase只能用個rowkey,或者乙個rowkey範圍即scan來查詢資料。所以 rowkey的設計是至關重要的,關係到你應用層的查詢效率。

rowkey是以字典順序排序的,儲存的是位元組碼。

根據rowkey範圍查詢的時候,一般是知道startrowkey,如果我們通過scan只傳startrowkey : d開頭的,那麼查詢的是所有比d大的都查了,而我們只需要d開頭的資料,那就要通過endrowkey來限制。我們可以通過設定endrowkey為:d 開頭,後面的根據你的rowkey組合來設定,一般是加比startkey大一位。比如說rowkey設計為:使用者id-日期,那麼查某個使用者某天的數 據,startkey為3231-20121212,endkey為:3231+201213,那麼你查到的就是使用者為3231在20121212這一天 的資料。

需要訪問的資料rowkey連續的話,scan到的有用資料比較多,利用率高,能夠避免或減少反覆記憶體倒換。

rowkey的設計和資料的分布有很大關係,rowkey設計的時候需要保證資料入庫時的併發度,但又不能過於分散。

可列舉屬性值較少的屬性放在rowkey前面

在rowkey中,需要放入多個屬性,這多個屬性的先後次序和訪問的效率有直接的關係。乙個普遍的規則是:數量較少,可控的屬性放在rowkey前面(如servicetype,cpid等);反之放在後面(如url,mxid等)。這樣做的原因是可控屬性放在前面,對各種不同查詢需求的平衡性強一些,反之平衡性較差。

案例1:

201010-rtsp-cp002-s-shenzhen-***-2servicetype可列舉,並且數量較少,分為http和rtsp兩種,放在前面; 

而cpid可能會比較多(假設有5個cp),因此放在後面。 

這樣的設計能夠適應如下兩種需求,複雜度都比較小: 

1) 查詢2023年10月所有cp的http資料。這種需求設定scan的startrow=『201010-http-』,endrow=『201010-http-z』,即可。 

2) 查詢2023年10月cp001的所有協議的資料。這種需求下,根據scan rowkey連續的原則,需要將查詢劃分成兩個scan,分別查詢http型別cp001的資料和rtsp型別cp001的資料。

但是,如果將cp放在前面,如下所示,適應性就差一些,如下所示案例2:

201010-cp002-rtsp-s-shenzhen-***-21) 查詢2023年10月cp001的所有協議的資料。 

這種需求下,設定scan的startrow=『201010-cp001-』,endrow=『201010-cp001-z』,即可。 

2) 查詢2023年10月,所有cp的http資料。 

這種需求下,根據scan的rowkey連續原則,需要將查詢分成cp001-http、cp002-http、cp003-http、cp004-http、cp005-http五個查詢進行,相對模型一複雜了一些。

業務訪問中權重高的key放在前面

例如urlrecords表的主要用途是用來計算當天的url訪問排名。根據業務需求,需要訪問某天的所有url,因此date是主鍵,權重更高,放在前面,而url則放在後面。

構造冗餘資料

例如,percontent的資料報含了url records的資料,url records的資料是冗餘儲存的,區別在於percontent的url放在date前面,而url records表的url放在date後面。這就是由於url在滿足不同需求的時候,權重不同,由於url records需要的資料量不大,因此採用冗餘的機制解決該矛盾。 

權衡需求的重要性和系統忍受度選擇一種方案 

當兩種需求有矛盾,但其中一方屬於次要需求,並且在系統忍受度範圍之內的話,可以捨棄一種方案。優先滿足需求更強的一方

時間屬性在rowkey中的使用

如果需要經常訪問特定時間段的資料,將時間屬性放在rowkey中是乙個較好的選擇。 

和利用時間戳來訪問特定時間段的資料方法相比,將時間屬性放在rowkey中具有可控性,容易將能夠同時訪問的資料相對集中存放的優點。 

時間屬性放在rowkey中需要注意資料分布和併發度的問題:hbase資料是按照rowkey排序的,時間屬性放在rowkey中容易造成資料總是在末尾寫入的情況,這種情況下併發度很差。這種情況可以通過在時間屬性前面增加prefix和提前預分region的方法解決。

迴圈key使用

(1)存在問題

如果rowkey中有時間屬性,並且隨著時間的增加,rowkey會不斷的增大下去的話,會造成region數量不斷地增加。如果使用ttl來控制資料的生命週期,一些老的資料就會過期,進而導致老的region資料量會逐漸減少甚至成為空的region。這樣一方面region總數在不斷增加,另外一方面老的region在不斷的成為空的region,而空的region不會自動合併,進而造成過多空的region占用負載和記憶體消耗的情況。 

(2)解決辦法

這種情況下,可以使用迴圈key的方法來解決。思路是根據資料的生命週期設定rowkey的迴圈週期,當乙個週期過去以後,通過時間對映的方法,繼續使用老的過期資料的rowkey。 

例如,key的格式如下: 

yy-mm-dd-url。如果資料的生命週期是一年,則可以使用mm-dd-url的格式。這樣當前一年過去以後,資料已經老化,後一年的資料可以繼續寫入前一年的位置,使用前一年資料的rowkey。這樣可以避免空的region占用資源的情況。

根據hbase的原理,key的週期需要至少比ttl大2* hbase.hregion.majorcompaction(預設24小時)的時間,才能夠保證過期的資料能夠在key迴圈回來之前得到完全清理。 

按照時間週期進行建表的方式也可以解決空region的問題,和迴圈key方法相比較,迴圈key的優點如下:

同樣,迴圈key具有如下劣勢:

如果在系統壓力不是特別大,需要長期執行,能夠控制查詢不會查詢到過期資料的場景下,建議使用ttl+迴圈key的方式,否則建議使用按照時間週期進行建表的方式。

通過rowkey設計來控制併發度

在相同業務模式下,不同的rowkey設計系統的併發度不一樣。和按天建表的思路類似,通過rowkey控制併發度的原則是啟用的region總數適中,每個regionserver的啟用region數大於1,小於(寫操作記憶體/flushsize)為宜。

為了實現這一點,可以將可列舉、數量有限的屬性放在rowkey的前面,時間放在後面的方式來提高併發度;通過將大粒度的時間屬性(如天、小時等)放在rowkey前面,數量很大的可列舉屬性(如**號碼、url等)放在後面的方法來控制啟用的region數。

HBase的RowKey設計原則

hbase是三維有序儲存的,通過rowkey 行鍵 column key column family和qualifier 和timestamp 時間戳 這個三個維度可以對hbase中的資料進行快速定位。hbase中rowkey可以唯一標識一行記錄,在hbase查詢的時候,有以下幾種方式 通過get方...

HBase的RowKey設計原則

hbase是三維有序儲存的,通過rowkey 行鍵 column key column family和qualifier 和timestamp 時間戳 這個三個維度可以對hbase中的資料進行快速定位。hbase中rowkey可以唯一標識一行記錄,在hbase查詢的時候,有以下幾種方式 通過get方...

hbase的rowkey設計原則

hbase是三維有序儲存的,通過rowkey 行鍵 column key column family和qualifier 和timestamp 時間戳 這個三個維度可以對hbase中的資料進行快速定位。hbase中rowkey可以唯一標識一行記錄,在hbase查詢的時候,有兩種方式 1 通過get方...