圖檔來自HBase企業應用…書籍
1 模式建立
1.1 hbase模式結構
Hbase的模式結構包括表、RowKey、列族、Timestamp(時間版本)。其實模式是一個三維有序結構,前面三個次元确定一行資料。
Hbase的模式不同于關系型資料庫(RDBMS),Hbase的單元格(cell)所在行是有序的,其列(Qualifier)在所屬列族(column family)存在的情況下 ,可以通過用戶端自由添加。對于這些名詞具體含義可以參考另一篇部落客寫的部落格 http://blog.csdn.net/wulantian/article/details/46786413
我們在設計HBase時候需要考慮不少因素:
1.這個表應該有多少個列族;
2.列粗使用什麼資料;
3.每個列族應該有多少列;
4.列名是什麼;
5.單元應該存放什麼資料;
6.每個單元存儲多少個時間版本;
7.行健(RowKey)結構是什麼。應該包含什麼資訊。
1.2 HBase設計需要注意兩個關鍵點:
(1)join
Hbase沒有join的概念,是以不支援join的操作,但是在不少業務中确需要不少的join操作。而大表結構可以解決這一問題,值需要一條行記錄加上一個特定的行關鍵字,就可以實作把所有的關于join的資料合并在一起。
(2)RowKey
RowKey是非常重要的,設計時候需要慎重考慮。如果RowKey是整形的,用二進制的方式應該比string來存儲一個資料更加節約空間。以存儲使用者購買商品為例,複合的RowKey由使用者Id作為字首,倒置的時間串作為RowKey的字尾可以使得我們了解使用者最新購買消費資訊,我們可以根絕這些推薦使用者最近需要什麼的産品,經常使用的推薦算法,我們可以根據使用者最近的消費商品推薦使用者最近還需要購買什麼産品。
2 RowKey設計根據實際情況選擇優化以下幾點
2.1 RowKey按字典順序從大到小排序
關系型資料庫可以在多列上建立索引,但是HBase隻能在RowKeya上面建立索引。RowKey是不可分割的位元組數,按字典順序由低到高存儲在表中。一個空的數組用來辨別空間的起始或者結尾。但是如果我們需要由大到小排列時候我們可以進行轉換,最大的變最小,最小的變最大,在應用層轉回來即可完成,采用RowKey=Integer.MAX_VALUE-RowKey方式轉換。
2.2 RowKey盡量散列設計
最重要的就是散列的保證,這樣就可以保證所有資料都不是在一個Region上,進而避免讀寫時候負載會集中在個别Region上。假設我們需要存儲一個視訊網站使用者的所有觀影記錄,這時候的RowKey可以設計成userId_videoId的拼接字元串,但是這樣設計的話userId的分布就很肯能不均勻,因為RowKey是按字元串排序的:我們可以采取三種辦法解決具體如下:
(1)反轉userId,将其字元串反轉後存儲;
(2)散列userId,即對userId進行散列;
(3)userId取模後MD5加密,取前6位作為字首加入到userId前面。
2.3 Rowkey的長度盡量要短
如果RowKey過長,第一存儲開銷會增加,影響存儲效率;第二記憶體中Rowkey字段過長,會導緻記憶體的使用率過低,進而降低索引命中率。一般做法:時間使用Long表示;盡量使用編碼壓縮。
3 列族(Column Family)
主要講一下列族的相關配置屬性,這些都是有預設值的,在建立表的時候我們也可以顯示的指定。列族是一些列的集合。一個列族的所有成員都有着相同的字首。比如列course:computer和course:english都是列族的成員。:是用來區分字首跟列名的,列族在建立表時候必須 聲明但是列不需要特别聲明,使用者可以随時建立新列。一個列族的成員在檔案系統都存儲在一起,因為存儲優化針對的是列族。目前HBase不能很好地處理多個列族。
好了下面該說一下列族的相關配置屬性了。
3.1 可配置的資料塊大小:
HFile資料塊大小可以在列族層設定,其預設值是65536位元組或者64KB,資料塊索引存儲每個HFile資料塊的起始鍵,資料塊越小索引越大,随機查找性能更好,代碼如下:
hbase(main)::> create 'mytable'
{NAME =>'colfam1',BLOCKSIZE=>'65536'}
3.2 資料塊緩存:
資料塊緩存預設是打開的,可以在建立表或者更改表時候關閉資料塊緩存屬性,代碼如下:
hbase(main)::>create'mytable', {NAME=>'colfam1',BLOCKCACHE=>'false'}
IN_MEMORY參數預設值是false,該值表示HBase除了在資料塊緩存中儲存這列族相比其他列族更激進之外,并不提供其他額外保證,下面展示如何設定的代碼:
hbase(main)::>create'mytable', {NAME=>'colfam1',IN_MEMORY=>'true'}
3.3 布隆過濾器
資料塊索引提供了一個有效的方法getDataBlockIndexReader(),在通路某個特定的行時候,用來查找讀取的HFile的資料塊,但是作用有限。布隆過濾器(Bloom Filter)允許對存儲在每個資料塊的資料做一個反向測驗,當查詢某行時先查詢布隆過濾器,看看改行是否不在這個資料塊,布隆過濾器的兩種回答:1,确定的回答行不在;2:不知道。布隆過濾器也可以應用到行内的單元格上,當通路某列的辨別符時候先使用同樣的反向檢驗。可以在列族上打開布隆過濾器,預設值是NONE,另外還有兩個值ROW表示行級布隆過濾器;ROWCOL表示列辨別符級布隆過濾器,代碼如下:
hbase(main)::>create'mytable', {NAME=>'colfam1',BLOOMFILTER =>'ROWCOL'}
3.4 資料壓縮
HBase可以使用多種壓縮編碼,包括LZO、SNAPPY、GZIP。隻在硬碟壓縮,記憶體中或者網絡傳輸中沒有壓縮
hbase(main)::>create'mytable', {NAME=>'colfam1',COMPRESSION=>'SNAPPY'}
3.5 單元時間版本
時間版本是在列族級設定的,隻需要一個時間版本時候,這樣子就不會保留更新單元的多個時間版本,代碼如下:
hbase(main)::>create'mytable', {NAME=>'colfam1',VERSIONS=>}
最小時間版本數,代碼如下:
hbase(main)::>create'mytable', {NAME=>'colfam1',VERSIONS=>,MIN_VERSIONS => '1'}
同一個建表語句中為列族指定多個屬性代碼如下:
hbase(main)::>create'mytable', {NAME=>'colfam1',VERSIONS => ,TTL=>'18000'}
3.6 生存時間
用于設定單元格的生存周期,單元格過滿則會将其删除,在列族cf1上設定TTL為18000s,cf1中超過時間的将會在下一次大合并時候删除。代碼如下:
hbase(main)::>create'mytable', {NAME=>'colfam1',TTL => '18000'}