天天看點

HBase的rowKey設計技巧

        本篇部落格小菌為大家帶來的是HBase的rowKey設計技巧!

        HBase是三維有序存儲的,通過rowkey(行鍵),column key(column family和qualifier)和TimeStamp(時間戳)這個三個次元可以對HBase中的資料進行快速定位。

        HBase中rowkey可以唯一辨別一行記錄,在HBase查詢的時候,有以下幾種方式:

通過get方式,指定rowkey擷取唯一一條記錄

通過scan方式,設定startRow和stopRow參數進行範圍比對

全表掃描,即直接掃描整張表中所有行記錄

        rowkey是一個二進制碼流,可以是任意字元串,最大長度64kb,實際應用中一般為10-100bytes,以byte[]形式儲存,一般設計成定長。

        建議越短越好,不要超過16個位元組,原因如下:

資料的持久化檔案HFile中是按照KeyValue存儲的,如果rowkey過長,比如超過100位元組,1000w行資料,光rowkey就要占用100*1000w=10億個位元組,将近1G資料,這樣會極大影響HFile的存儲效率;

MemStore将緩存部分資料到記憶體,如果rowkey字段過長,記憶體的有效使用率就會降低,系統不能緩存更多的資料,這樣會降低檢索效率。

        如果rowkey按照時間戳的方式遞增,不要将時間放在二進制碼的前面,建議将rowkey的高位作為散列字段,由程式随機生成,低位放時間字段,這樣将提高資料均衡分布在每個RegionServer,以實作負載均衡的幾率。如果沒有散列字段,首字段直接是時間資訊,所有的資料都會集中在一個RegionServer上,這樣在資料檢索的時候負載會集中在個别的RegionServer上,造成熱點問題,會降低查詢效率。

        必須在設計上保證其唯一性,rowkey是按照字典順序排序存儲的,是以,設計rowkey的時候,要充分利用這個排序的特點,将經常讀取的資料存儲到一塊,将最近可能會被通路的資料放到一塊。

        HBase中的行是按照rowkey的字典順序排序的,這種設計優化了scan操作,可以将相關的行以及會被一起讀取的行存取在臨近位置,便于scan。然而糟糕的rowkey設計是熱點的源頭。

        熱點發生在大量的client直接通路叢集的一個或極少數個節點(通路可能是讀,寫或者其他操作)。大量通路會使熱點region所在的單個機器超出自身承受能力,引起性能下降甚至region不可用,這也會影響同一個RegionServer上的其他region,由于主機無法服務其他region的請求。

        設計良好的資料通路模式以使叢集被充分,均衡的利用。為了避免寫熱點,設計rowkey使得不同行在同一個region,但是在更多資料情況下,資料應該被寫入叢集的多個region,而不是一個。下面是一些常見的避免熱點的方法以及它們的優缺點:

        這裡所說的加鹽不是密碼學中的加鹽,而是在rowkey的前面增加随機數,具體就是給rowkey配置設定一個随機字首以使得它和之前的rowkey的開頭不同。配置設定的字首種類數量應該和你想使用資料分散到不同的region的數量一緻。加鹽之後的rowkey就會根據随機生成的字首分散到各個region上,以避免熱點。

        哈希會使同一行永遠用一個字首加鹽。哈希也可以使負載分散到整個叢集,但是讀卻是可以預測的。使用确定的哈希可以讓用戶端重構完整的rowkey,可以使用get操作準确擷取某一個行資料。

第三種防止熱點的方法時反轉固定長度或者數字格式的rowkey。這樣可以使得rowkey中經常改變的部分(最沒有意義的部分)放在前面。這樣可以有效的随機rowkey,但是犧牲了rowkey的有序性。

反轉rowkey的例子以手機号為rowkey,可以将手機号反轉後的字元串作為rowkey,這樣的就避免了以手機号那樣比較固定開頭導緻熱點問題

        一個常見的資料處理問題是快速擷取資料的最近版本,使用反轉的時間戳作為rowkey的一部分對這個問題十分有用,可以用 Long.Max_Value - timestamp 追加到key的末尾,例如 [key][reverse_timestamp] , [key] 的最新值可以通過scan [key]獲得[key]的第一條記錄,因為HBase中rowkey是有序的,第一條記錄是最後錄入的資料。

        其他一些建議:

        盡量減少行鍵和列族的大小在HBase中,value永遠和它的key一起傳輸的。當具體的值在系統間傳輸時,它的rowkey,列名,時間戳也會一起傳輸。如果你的rowkey和列名很大,這個時候它們将會占用大量的存儲空間。

        列族盡可能越短越好,最好是一個字元。

        冗長的屬性名雖然可讀性好,但是更短的屬性名存儲在HBase中會更好。

        本次的分享就到這裡了,受益的小夥伴或對大資料技術感興趣的朋友記得關注小菌喲(^U^)ノ~YO

HBase的rowKey設計技巧