天天看點

hbase:rowkey的設計原則

rowkey設計原則和方法

rowkey設計首先應當遵循三大原則:

rowkey長度原則

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

一般越短越好,不要超過16個位元組,注意原因如下:

1、目前作業系統都是64位系統,記憶體8位元組對齊,控制在16位元組,8位元組的整數倍利用了作業系統的最佳特性。

2、hbase将部分資料加載到記憶體當中,如果rowkey過長,記憶體的有效使用率就會下降。

rowkey散列原則

如果rowkey按照時間戳的方式遞增,不要将時間放在二進制碼的前面,建議将rowkey的高位位元組采用散列字段處理,由程式随即生成。低位放時間字段,這樣将提高資料均衡分布,各個regionServer負載均衡的幾率。

如果不進行散列處理,首字段直接使用時間資訊,所有該時段的資料都将集中到一個regionServer當中,這樣當檢索資料時,負載會集中到個别regionServer上,造成熱點問題,會降低查詢效率。

rowkey唯一原則

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

是以良好的rowkey設計,應當遵循三大原則,并且能讓資料分散,進而避免熱點問題。本節介紹幾種常用的rowkey設計方法,以供同學們學習。

注意:本節理論知識較多,不過都是大資料崗位面試中常見問題,希望同學們認真研讀。

1.1 加鹽

這裡所說的加鹽并非密碼學中的加鹽,而是在rowkey的前面配置設定随機數,當給rowkey随機字首後,它就能分布到不同的region中,這裡的字首應該和你想要資料分散的不同的region的數量有關。

為了讓同學們更好的了解加鹽(salting)這個rowkey設計方法。我們以電信公司為例。當我們去電信公司列印電話詳單也就是通話記錄。對于通話記錄來說,每個人每月可能都有很多通話記錄,而使用電信的使用者也是億計。這種資訊,我們就能存入hbase當中。

對于通話記錄,我們有什麼資訊需要儲存呢?首先,肯定應該有主叫和被叫,然後有主叫被叫之間的通話時長,以及通話時間。除此之外,還應該有主叫的位置資訊,和被叫的位置資訊。

由此,我們的通話記錄表需要記錄的資訊就出來了:主叫、被叫、時長、時間、主叫位置、被叫位置。

我們該如何來設計一張hbase表呢?

首先,hbase表是依靠rowkey來定位的,我們應該将盡可能多的将查詢的資訊編入rowkey當中。hbase的中繼資料表mate表就給我們了一個很好的示例。它包括了namespace,表名,startKey,時間戳,計算出來的碼(用于分散資料)。

是以,當我們設計通話記錄的rowkey時,需要将能唯一确定該條記錄的資料編入rowkey當中。即是需要将主叫、被叫、時間編入。

如下所示:

17765657979 18688887777 201806121502 #主叫,被叫,時間
           

但是我們能否将我們設計的rowkey真正應用呢?

當然是可以的,但是熱點問題便會随之而來。

例如你的電話是以177開頭,電信的hbase叢集有500台,你的資料就隻可能被存入一台或者兩台機器的region當中,當你需要列印自己的通話記錄時,就隻有一台機器為你服務。而若是你的資料均勻分散到500機器中,就是整個叢集為你服務。兩者之間效率速度差了不止一個數量級。

注意:由于我們的regionServer就隻有一台,沒有叢集環境,是以我們隻介紹方法和理論操作,不提供實際結果

因為我們設定整個hbase叢集有500台,是以我們随機在0-499之間中随機數字,添加到rowkey首部。

如下所示:

12 17765657979 18688887777 201806121502 #随機數,主叫,被叫,時間
           

在插入資料時,判斷首部随機數字,選擇對應的region存入,由于rowkey首部數字随機,是以資料也将随機分布到不同的regionServer中。這樣就能很好的避免熱點問題了。

1.2 預分區

通常hbase會自動處理region拆分,當region的大小到達一定門檻值後,region将被拆分成兩個,之後在兩個region都能繼續增長資料。

然而在這個過程當中,會出現兩個問題:

第一點,就是我們所說的熱點問題,資料會繼續往一個region中寫,出現寫熱點問題;

第二點,則是

拆分合并風暴

,當使用者的region大小以恒定的速度增長,region的拆分會在同一時間發生,因為同時需要

壓縮

region中的存儲檔案,這個過程會重寫拆分後的region,這将會引起磁盤I/O上升 。

壓縮:hbase支援大量的壓縮算法,而且通常開啟壓縮,因為cpu壓縮和解壓的時間比從磁盤讀寫資料的時間消耗的更短,是以壓縮會帶來性能的提升。

對于拆分合并風暴,通常我們需要關閉hbase的自動管理拆分。然後手動調用hbase的split(拆分)和major_compact(壓縮),對其進行時間控制,來分散I/O負載。但是其中的split操作同樣是高I/O的操作。

為了解決這些問題,預分區就是一種很好的方法,通常它和

加鹽

結合起來使用。

所謂預分區,就是預先建立hbase表分區。這需要我們明确rowkey的取值範圍和構成邏輯。

比如前面我們所列舉的電信電話詳單表。通過加鹽我們得到的 rowkey構成是:

随機數+主叫+被叫+時間

,如果我們現在并沒有500台機器,隻有10台,但是按照我們的計劃,未來将擴充到500台的規模。是以我們仍然設計0到499的随機數,但是将以主叫177開頭的通話記錄配置設定到十個region當中,是以我們将随機數均分成十個區域,範圍如下:

-50,50-100,100-150,150-200,200-250,250-300,300-350,350-400,400-450,450-
           

然後我們将我們的預分區存入數組當中,當插入資料時,先根據插入資料的首部随機數,判斷分區位置,再進行插入資料。同樣,這樣也能使得各台節點負載均衡。

1.3 哈希

細心的同學可能會發現,在我們剛剛提出的

加鹽

預分區

rowkey設計方法中,并沒有完整運用到rowkey設計的散列原則。

更一步思考下,我們會發現如果隻運用

加鹽

預分區

rowkey設計方法,資料會真正無序随即分布在hbase叢集當中,這并沒有讓我們利用到hbase根據字典順序排序的這一特點。

由此,哈希這一設計理念便順理成章的出現在我們眼前。

同樣以電信通話記錄為例,我們想将某一天的通話記錄存入同一region當中,是以我們利用哈希函數算出哈希值,再模以我們需要存入region數量,我們就能将相同輸入的資料,存入同一region當中。

主叫,被叫,時間

rowkey當中,我們将callerID(主叫)與 20180612(某一天的時間)作為參數,傳入哈希函數當中,将得到的哈希值模以500,餘數添加到rowkey首部中,再結合

預分區

設計方法,就能将資料均勻分布到regionServer當中。

同時,我們還能将相同rowkey的資料收集到一台節點上,在避免熱點問題的情況下,充分利用hbase字典排序的優點。

1.4 反轉

對于以手機号碼這樣比較固定開頭的rowkey(例如開頭177,159,138),但是它的後幾位都是随機的,沒有規律的。我們可以将手機号反轉之後作為rowkey,這樣就避免了熱點問題。

這就是rowkey設計的另一種方法

反轉

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

=================================================================================================

一條資料的唯一辨別就是rowkey,那麼這條資料存儲于哪個分區,取決于rowkey處于哪個一個預分區的區間内,設計rowkey的主要目的 ,就是讓資料均勻的分布于所有的region中,在一定程度上防止資料傾斜。接下來我們就談一談rowkey常用的設計方案。

1.生成随機數、hash、散列值

比如:

原本rowKey為1001的,SHA1(安全雜湊演算法)後變成:dd01903921ea24941c26a48f2cec24e0bb0e8cc7

原本rowKey為3001的,SHA1後變成:49042c54de64a1e9bf0b33e00245660ef92dc7bd

原本rowKey為5001的,SHA1後變成:7b61dec07e02c188790670af43e717f0f46e8913

在做此操作之前,一般我們會選擇從資料集中抽取樣本,來決定什麼樣的rowKey來Hash後作為每個分區的臨界值。

2.字元串反轉

20170524000001轉成10000042507102

20170524000002轉成20000042507102

這樣也可以在一定程度上散列逐漸put進來的資料。

3.字元串拼接

20170524000001_a12e

20170524000001_93i7

設計RowKey時,要充分排序存儲這個特性,将經常一起讀取的行存儲放到一起。(位置相關性)

繼續閱讀