干货 | 大白话彻底搞懂 HBase RowKey 详细设计
作者 |?且聽風吟
責編 | Carol
封圖 |?CSDN?付費下載于視覺中國
前言
RowKey作為HBase的核心知識點,RowKey設計會影響到數據在HBase中的分布,還會影響我們查詢效率,所以RowKey的設計質量決定了HBase的質量。是咱們大數據從業者必知必會的,自然也是面試必問的考察點。
那么rowkey到底是什么呢?原理是什么呢?怎么設計RowKey呢?使用場景是怎樣的呢?有哪些設計原則呢?又如何進行優化呢?
下面就讓我們帶著這些問題,一起探索RowKey的世界!
RowKey的概念
RowKey從字面意思來看是行鍵的意思,咱們知道HBase可以理解為一個nosql(not only sql)數據庫,既然是數據庫,那么咱們日常使用最多的就是增刪改查(curd)。其實在增刪改查的過程中RowKey就充當了主鍵的作用,它和眾多的nosql數據庫一樣,可以唯一的標識一行記錄。
RowKey行鍵 (RowKey)可以是任意字符串,在HBase內部,RowKey保存為字節數組。存儲時,數據按照RowKey的字典序(byte order)排序存儲。設計RowKey時,要充分利用排序存儲這個特性,將經常一起讀取的行存儲放到一起。
RowKey的特點小結如下:
RowKey類似于主鍵,可以唯一的標識一行記錄;
由于數據按照RowKey的字典序(byte order)排序存儲,因此HBase中的數據永遠都是有序的。
RowKey可以由用戶自己指定,只要保證這個字符串不重復就可以了。
知識點補充:在HBase中檢索數據時使用到RowKey的一共有三種方式:
get:通過指定單個RowKey來獲取對應的唯一一條記錄;
like:通過RowKey的range來進行匹配;
scan:通過設置startRow和stopRow參數來進行范圍匹配(注意:如果不設置就是全表掃描)。
RowKey的作用
要了解RowKey的作用,首先我們需要知道在HBase中,一個Region就相當于一個數據分片,每個Region都有StartRowKey和StopRowKey(用來表示 Region存儲的RowKey的范圍),HBase表里面的數據是按照RowKey來分散存儲到不同的Region里面的。
為了避免熱點現象咱們需要將數據記錄均衡的分散到不同的Region中去,因此需要RowKey滿足這種散列的特點。此外,在數據讀寫過程中也是與RowKey密切相關的。RowKey的作用可以歸納如下:
Hbase在讀寫數據時需要通過RowKey找到對應的Region;
MemStore和HFile中的數據都是按照 RowKey 的字典序排序。
那到底啥是熱點現象呢?咱們接著分析!
熱點現象
4.1、熱點現象怎么產生
我們知道HBase中的行是按照rowkey的字典順序排序的,這種設計優化了 scan操作,可以將相關的行以及會被一起讀取的行存取在臨近位置,便于 scan讀取。
然而萬事萬物都有兩面性,在咱們實際生產中,當大量請求訪問HBase集群的一個或少數幾個節點,造成少數RegionServer的讀寫請求過多,負載過大,而其他RegionServer負載卻很小,這樣就造成熱點現象(吐槽:其實和數據傾斜類似,還整這么高大上的名字)。
掌握了熱點現象的概念,我們就應該知道大量的訪問會使熱點Region所在的主機負載過大,引起性能下降,甚至導致Region不可用。所以我們在向HBase中插入數據的時候,應優化RowKey的設計,使數據被寫入集群的多個region,而不是一個。盡量均衡地把記錄分散到不同的Region中去,平衡每個Region的壓力。
其實RowKey的優化主要就是在解決怎么避免熱點現象。那么有哪些避免熱點現象的方法呢?各有什么缺點?帶著問題,接著往下看。
4.2、如何避免熱點現象(RowKey的優化)
在日常使用中,主要有3個方法來避免熱點現象,分別是反轉,加鹽和哈希。聽起來很奇怪,下面咱們逐個舉例詳細分析:
4.2.1 反轉(Reversing)
第一種咱們要分析的方法是反轉,顧名思義它就是把固定長度或者數字格式的 rowkey進行反轉,反轉分為一般數據反轉和時間戳反轉,其中以時間戳反轉較常見。
適用場景:
比如咱們初步設計出的RowKey在數據分布上不均勻,但RowKey尾部的數據卻呈現出了良好的隨機性(注意:隨機性強代表經常改變,沒意義,但分布較好),此時,可以考慮將RowKey的信息翻轉,或者直接將尾部的bytes提前到RowKey的開頭。反轉可以有效的使RowKey隨機分布,但是反轉后有序性肯定就得不到保障了,因此它犧牲了RowKey的有序性。
缺點:
利于Get操作,但不利于Scan操作,因為數據在原RowKey上的自然順序已經被打亂。
舉例:
比如咱們通常會有需要快速獲取數據的最近版本的數據處理需求,這時候就需要把時間戳作為RowKey來查詢了,但是時間戳正常情況下是這樣的:
1588610367373 1588610367396前面這部分是相同的,在查詢的時候就容易造成熱點現象,因此需要使用時間戳反轉的方式來處理。實際生產中可以用 Long.Max_Value - timestamp 追加到 key 的末尾,比如 [key][reverse_timestamp], [key] 的最新值可以通過 scan [key]獲得[key]的第一條記錄,因為HBase中RowKey是有序的,所以第一條記錄是最后錄入的數據。
常見的場景,比如需要保存一個用戶的操作記錄,就可以按照操作時間倒序排序,在設計rowkey的時候,可以這樣設計 [反轉后的userId][Long.Max_Value - timestamp],在查詢用戶的所有操作記錄數據的時候,直接指定反轉后的userId,startRow 是 [反轉后的userId][000000000000],stopRow 是 [反轉后的userId][Long.Max_Value - timestamp]。如果需要查詢某段時間的操作記錄,startRow 是[反轉后的userId[Long.Max_Value - 起始時間], stopRow 是[反轉后的userId][Long.Max_Value - 結束時間]。
4.2.2 加鹽(Salting)
第二種咱們要介紹的方法是加鹽,玩過密碼學的可能知道密碼學里也有加鹽的方法,但是咱們RowKey的加鹽和密碼學不一樣,它的原理是在原RowKey的前面添加固定長度的隨機數,也就是給RowKey分配一個隨機前綴使它和之前的RowKey的開頭不同。
適用場景:
比如咱們設計的RowKey是有意義的,但是數據類似,隨機性比較低,反轉也沒法保證隨機性,這樣就沒法根據RowKey分配到不同的Region里,這時候就可以使用加鹽的方式了。
需要注意隨機數要能保障數據在所有Regions間的負載均衡,也就是說分配的隨機前綴的種類數量應該和你想把數據分散到的那些region的數量一致。只有這樣,加鹽之后的rowkey才會根據隨機生成的前綴分散到各個region中,避免了熱點現象。
缺點:
大白話來理解就是加了鹽就嘗不到原有的味道了。因為添加的是隨機數,添加后如果還基于原RowKey查詢,就無法知道隨機數是什么,那樣在查詢的時候就需要去各個可能的Region中查找,同時加鹽對于讀取是利空的。并且加鹽這種方式增加了讀寫時的吞吐量。
4.2.3 哈希(Hashing)
最后介紹大家最熟悉的哈希方法,不管是學的啥技術,都會涉及到哈希,也都大同小異,比較簡單。
這里的哈希是基于RowKey的完整或部分數據進行Hash,而后將哈希后的值完整替換或部分替換原RowKey的前綴部分。這里說的hash常用的有MD5、sha1、sha256 或 sha512 等算法。
適用場景:
其實哈希和加鹽的適用場景類似,但是由于加鹽方法的前綴是隨機數,用原rowkey查詢時不方便,因此出現了哈希方法,由于哈希是使用各種常見的算法來計算出的前綴,因此哈希既可以使負載分散到整個集群,又可以輕松讀取數據。
缺點:
與反轉類似,哈希也打亂了RowKey的自然順序,因此也不利于Scan。
RowKey設計原則
通過前面的分析我們應該知道了HBase中RowKey設計的重要性了,為了幫助我們設計出完美的RowKey,HBase提出了RowKey的設計原則,一共有四點:長度原則、唯一原則、排序原則,散列原則。
RowKey在字段的選擇上,需要遵循的最基本原則是唯一原則,因為RowKey必須能夠唯一的識別一行數據。無論應用的負載特點是什么樣,RowKey字段都應該首先考慮最高頻的查詢場景。數據庫通常都是以如何高效的讀取和消費數據為目的,而不僅僅是數據存儲本身。然后再結合具體的負載特點,再對選取的RowKey字段值進行改造,結合RowKey的優化,也就是避免熱點現象的那些方法來優化就可以了。
5.1 長度原則
RowKey本質上是一個二進制碼的流,可以是任意字符串,最大長度為64kb,實際應用中一般為10-100byte,以byte[]數組形式保存,一般設計成定長。官方建議越短越好,不要超過16個字節,原因可以概括為如下幾點:
影響HFile的存儲效率:HBase里的數據在持久化文件HFile中其實是按照Key-Value對形式存儲的。這時候如果RowKey很長,比如達到了200byte,那么僅僅1000w行的記錄,只考慮RowKey就需占用近2GB的空間,極大的影響了HFile的存儲效率。
降低檢索效率:由于MemStore會緩存部分數據到內存中,如果RowKey比較長,就會導致內存的有效利用率降低,也就不能緩存更多的數據,從而降低檢索效率。
16字節是64位操作系統的最佳選擇:64位系統,內存8字節對齊,控制在16字節,8字節的整數倍利用了操作系統的最佳特性。
5.2 唯一原則
其實唯一原則咱們可以結合HashMap的源碼設計或者主鍵的概念來理解,由于RowKey用來唯一標識一行記錄,所以必須在設計上保證RowKey的唯一性。
需要注意:由于HBase中數據存儲的格式是Key-Value對格式,所以如果向HBase中同一張表插入相同RowKey的數據,則原先存在的數據會被新的數據給覆蓋掉(和HashMap效果相同)。
5.3 排序原則
HBase會把RowKey按照ASCII進行自然有序排序,所以反過來我們在設計RowKey的時候可以根據這個特點來設計完美的RowKey,好好的利用這個特性就是排序原則。
5.4 散列原則
散列原則用大白話來講就是咱們設計出的RowKey需要能夠均勻的分布到各個RegionServer上。
比如設計RowKey的時候,當Rowkey 是按時間戳的方式遞增,就不要將時間放在二進制碼的前面,可以將 Rowkey 的高位作為散列字段,由程序循環生成,可以在低位放時間字段,這樣就可以提高數據均衡分布在每個Regionserver實現負載均衡的幾率。
結合前面分析的熱點現象的起因,思考:
如果沒有散列字段,首字段只有時間信息,那就會出現所有新數據都在一個 RegionServer上堆積的熱點現象,這樣在做數據檢索的時候負載將會集中在個別RegionServer上,不分散,就會降低查詢效率。
HBase里的RowKey是按照字典序存儲,因此在設計RowKey時,咱們要充分利用這個排序特點,將經常一起讀取的數據存儲到一塊,將最近可能會被訪問的數據放在一塊。如果最近寫入HBase表中的數據是最可能被訪問的,可以考慮將時間戳作為row key的一部分,由于是字典序排序,所以可以使用Long.MAX_VALUE - timestamp作為row key,這樣能保證新寫入的數據在讀取時可以被快速找到。
總結
看到這里RowKey的各個方面應該都已經搞懂了,本文從RowKey的原理,可能出現的問題,如何優化及各個優化措施對應的缺點和適用的場景,設計原則等角度對RowKey進行了詳細全面的解析,相信一定能對你有所幫助。
版權聲明:本文為CSDN博主「且聽_風吟」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_26803795/article/details/105994960
推薦閱讀那天我去逛街,發現連大編程語言都擺起地攤了……
研發的未來在哪里?Serverless 云開發來了!
從地攤看云計算:規模產業歷程大揭秘
國外小伙怒噴加密貨幣行業:入行兩年,我受夠了!
重構ncnn,騰訊優圖開源新一代移動端推理框架TNN
墨奇科技湯林鵬:如何用 AI 技術顛覆指紋識別?
性能超越最新序列推薦模型,華為諾亞方舟提出記憶增強的圖神經網絡
真香,朕在看了!
總結
以上是生活随笔為你收集整理的干货 | 大白话彻底搞懂 HBase RowKey 详细设计的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大数据,凉了?
- 下一篇: 数据爆炸时代,浪潮K1 Power释放新