HBase學習之路 (十)HBase表的設計原則

建表高級屬性

  下面幾個 shell 命令在 hbase 操做中能夠起到很大的做用,且主要體如今建表的過程當中,看 下面幾個 create 屬性正則表達式

一、 BLOOMFILTER

  默認是 NONE 是否使用布隆過慮及使用何種方式,布隆過濾能夠每列族單獨啓用 使用 HColumnDescriptor.setBloomFilterType(NONE | ROW | ROWCOL) 對列族單獨啓用布隆算法

  Default = ROW 對行進行布隆過濾shell

  對 ROW,行鍵的哈希在每次插入行時將被添加到布隆apache

  對 ROWCOL,行鍵 + 列族 + 列族修飾的哈希將在每次插入行時添加到布隆api

  使用方法: create 'table',{BLOOMFILTER =>'ROW'}緩存

  做用:用布隆過濾能夠節省讀磁盤過程,能夠有助於下降讀取延遲併發

二、 VERSIONS

  默認是 1 這個參數的意思是數據保留 1 個 版本,若是咱們認爲咱們的數據沒有這麼大 的必要保留這麼多,隨時都在更新,而老版本的數據對咱們毫無價值,那將此參數設爲 1 能 節約 2/3 的空間app

  使用方法: create 'table',{VERSIONS=>'2'}負載均衡

  附:MIN_VERSIONS => '0'是說在 compact 操做執行以後,至少要保留的版本dom

三、 COMPRESSION

  默認值是 NONE 即不使用壓縮,這個參數意思是該列族是否採用壓縮,採用什麼壓縮算 法,方法: create 'table',{NAME=>'info',COMPRESSION=>'SNAPPY'} ,建議採用 SNAPPY 壓縮算 法 ,HBase 中,在 Snappy 發佈以前(Google 2011 年對外發布 Snappy),採用的 LZO 算法,目標是達到儘量快的壓縮和解壓速度,同時減小對 CPU 的消耗;

  在 Snappy 發佈以後,建議採用 Snappy 算法(參考《HBase: The Definitive Guide》),具體 能夠根據實際狀況對 LZO 和 Snappy 作過更詳細的對比測試後再作選擇。

  若是建表之初沒有壓縮,後來想要加入壓縮算法,能夠經過 alter 修改 schema

四、 TTL

  默認是 2147483647 即:Integer.MAX_VALUE 值大概是 68 年,這個參數是說明該列族數據的存活時間,單位是 s

  這個參數能夠根據具體的需求對數據設定存活時間,超過存過期間的數據將在表中不在 顯示,待下次 major compact 的時候再完全刪除數據

  注意的是 TTL 設定以後 MIN_VERSIONS=>'0' 這樣設置以後,TTL 時間戳過時後,將所有 完全刪除該 family 下全部的數據,若是 MIN_VERSIONS 不等於 0 那將保留最新的 MIN_VERSIONS 個版本的數據,其它的所有刪除,好比 MIN_VERSIONS=>'1' 屆時將保留一個 最新版本的數據,其它版本的數據將再也不保存。

五、 alter

使用方法:

  如 修改壓縮算法

disable 'table'

alter 'table',{NAME=>'info',COMPRESSION=>'snappy'}

enable 'table'

  可是須要執行 major_compact 'table' 命令以後 纔會作實際的操做。 

六、 describe/desc

  這個命令查看了 create table 的各項參數或者是默認值。

  使用方式:describe 'user_info'

七、 disable_all/enable_all

  disable_all 'toplist.*' disable_all 支持正則表達式,並列出當前匹配的表的以下:

 toplist_a_total_1001
 toplist_a_total_1002
 toplist_a_total_1008
 toplist_a_total_1009
 toplist_a_total_1019
 toplist_a_total_1035
 ...
 Disable the above 25 tables (y/n)? 並給出確認提示

八、 drop_all

  這個命令和 disable_all 的使用方式是同樣的

九、 hbase 預分區

  默認狀況下,在建立 HBase 表的時候會自動建立一個 region 分區,當導入數據的時候, 全部的 HBase 客戶端都向這一個 region 寫數據,直到這個 region 足夠大了才進行切分。一 種能夠加快批量寫入速度的方法是經過預先建立一些空的 regions,這樣當數據寫入 HBase 時,會按照 region 分區狀況,在集羣內作數據的負載均衡。

命令方式:

# create table with specific split points
hbase>create 'table1','f1',SPLITS => ['\x10\x00', '\x20\x00', '\x30\x00', '\x40\x00']
# create table with four regions based on random bytes keys
hbase>create 'table2','f1', { NUMREGIONS => 8 , SPLITALGO => 'UniformSplit' }
# create table with five regions based on hex keys
hbase>create 'table3','f1', { NUMREGIONS => 10, SPLITALGO => 'HexStringSplit'

  也可使用 api 的方式:

hbase org.apache.hadoop.hbase.util.RegionSplitter test_table HexStringSplit -c 10 -f info

hbase org.apache.hadoop.hbase.util.RegionSplitter splitTable HexStringSplit -c 10 -f info

參數:

  test_table 是表名

  HexStringSplit 是split 方式

  -c 是分 10 個 region

  -f 是 family

可在 UI 上查看結果,如圖:

  這樣就能夠將表預先分爲 15 個區,減小數據達到 storefile 大小的時候自動分區的時間 消耗,而且還有以一個優點,就是合理設計 rowkey 能讓各個 region 的併發請求平均分配(趨 於均勻) 使 IO 效率達到最高,可是預分區須要將 filesize 設置一個較大的值,設置哪一個參數 呢 hbase.hregion.max.filesize 這個值默認是 10G 也就是說單個 region 默認大小是 10G

  這個參數的默認值在 0.90 到 0.92 到 0.94.3 各版本的變化:256M--1G--10G

  可是若是 MapReduce Input 類型爲 TableInputFormat 使用 hbase 做爲輸入的時候,就要注意 了,每一個 region 一個 map,若是數據小於 10G 那隻會啓用一個 map 形成很大的資源浪費, 這時候能夠考慮適當調小該參數的值,或者採用預分配 region 的方式,並將檢測若是達到 這個值,再手動分配 region。

表設計

一、列簇設計

  追求的原則是:在合理範圍內能儘可能少的減小列簇就儘可能減小列簇。

  最優設計是:將全部相關性很強的 key-value 都放在同一個列簇下,這樣既能作到查詢效率 最高,也能保持儘量少的訪問不一樣的磁盤文件。

  以用戶信息爲例,能夠將必須的基本信息存放在一個列族,而一些附加的額外信息能夠放在 另外一列族。

二、RowKey 設計

  HBase 中,表會被劃分爲 1...n 個 Region,被託管在 RegionServer 中。Region 二個重要的 屬性:StartKey 與 EndKey 表示這個 Region 維護的 rowKey 範圍,當咱們要讀/寫數據時,如 果 rowKey 落在某個 start-end key 範圍內,那麼就會定位到目標 region 而且讀/寫到相關的數 據

  那怎麼快速精準的定位到咱們想要操做的數據,就在於咱們的 rowkey 的設計了

Rowkey 設計三原則

 一、 rowkey 長度原則

  Rowkey 是一個二進制碼流,Rowkey 的長度被不少開發者建議說設計在 10~100 個字節,不 過建議是越短越好,不要超過 16 個字節。

  緣由以下:

    一、數據的持久化文件 HFile 中是按照 KeyValue 存儲的,若是 Rowkey 過長好比 100 個字 節,1000 萬列數據光 Rowkey 就要佔用 100*1000 萬=10 億個字節,將近 1G 數據,這會極大 影響 HFile 的存儲效率;

    二、MemStore 將緩存部分數據到內存,若是 Rowkey 字段過長內存的有效利用率會下降, 系統將沒法緩存更多的數據,這會下降檢索效率。所以 Rowkey 的字節長度越短越好。

    三、目前操做系統是都是 64 位系統,內存 8 字節對齊。控制在 16 個字節,8 字節的整數 倍利用操做系統的最佳特性。

二、rowkey 散列原則

  若是 Rowkey 是按時間戳的方式遞增,不要將時間放在二進制碼的前面,建議將 Rowkey 的高位做爲散列字段,由程序循環生成,低位放時間字段,這樣將提升數據均衡分佈在每一個 Regionserver 實現負載均衡的概率。若是沒有散列字段,首字段直接是時間信息將產生全部 新數據都在一個 RegionServer 上堆積的熱點現象,這樣在作數據檢索的時候負載將會集中 在個別 RegionServer,下降查詢效率。

三、 rowkey 惟一原則

  必須在設計上保證其惟一性。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 是有序的,第一條記錄是最後錄入的數據。好比須要保存一個用戶的操 做記錄,按照操做時間倒序排序,在設計 rowkey 的時候,能夠這樣設計 [userId 反轉][Long.Max_Value - timestamp],在查詢用戶的全部操做記錄數據的時候,直接指 定 反 轉 後 的 userId , startRow 是 [userId 反 轉 ][000000000000],stopRow 是 [userId 反 轉][Long.Max_Value - timestamp]

  若是須要查詢某段時間的操做記錄,startRow 是[user 反轉][Long.Max_Value - 起始時間], stopRow 是[userId 反轉][Long.Max_Value - 結束時間]

相關文章
相關標籤/搜索