Hbase高级应用:建表高级属性、行键设计、设计原则、热点问题
Hbase建表高級(jí)屬性
1、BLOOMFILTER
默認(rèn)是NONE 是否使用布隆過(guò)慮及使用何種方式?
布隆過(guò)濾可以每列族單獨(dú)啟用。?
使用?HColumnDescriptor.setBloomFilterType(NONE | ROW | ROWCOL)?對(duì)列族單獨(dú)啟用布隆。
- Default = ROW 對(duì)行進(jìn)行布隆過(guò)濾。
- 對(duì) ROW,行鍵的哈希在每次插入行時(shí)將被添加到布隆。
- 對(duì) ROWCOL,行鍵 + 列族 + 列族修飾的哈希將在每次插入行時(shí)添加到布隆?
使用方法: create ‘table’,{BLOOMFILTER =>’ROW’}?
啟用布隆過(guò)濾可以節(jié)省讀磁盤過(guò)程,可以有助于降低讀取延遲
2、VERSIONS
默認(rèn)是1 這個(gè)參數(shù)的意思是數(shù)據(jù)保留1個(gè) 版本,如果認(rèn)為我們的老版本數(shù)據(jù)對(duì)我們毫無(wú)價(jià)值不需要保留這么多,且更新頻繁,那將此參數(shù)設(shè)為1 能節(jié)約2/3的空間。?
使用方法:?create 'table',{VERSIONS=>'2'}
附:MIN_VERSIONS => ‘0’是說(shuō)在compact操作執(zhí)行之后,至少要保留的版本
3、COMPRESSION
默認(rèn)值是NONE 即不使用壓縮?
這個(gè)參數(shù)意思是該列族是否采用壓縮,采用什么壓縮算法?
使用方法:?create 'table',{NAME=>'info',COMPRESSION=>'SNAPPY'}?
建議采用SNAPPY壓縮算法?
HBase中,在Snappy發(fā)布之前(Google 2011年對(duì)外發(fā)布Snappy),采用的LZO算法,目標(biāo)是達(dá)到盡可能快的壓縮和解壓速度,同時(shí)減少對(duì)CPU的消耗;?
在Snappy發(fā)布之后,建議采用Snappy算法(參考《HBase: The Definitive Guide》),具體可以根據(jù)實(shí)際情況對(duì)LZO和Snappy做過(guò)更詳細(xì)的對(duì)比測(cè)試后再做選擇。
| GZIP | 13.4% | 21 MB/s | 118 MB/s |
| LZO | 20.5% | 135 MB/s | 410 MB/s |
| Zippy/Snappy | 22.2% | 172 MB/s | 409 MB/s |
如果建表之初沒(méi)有壓縮,后來(lái)想要加入壓縮算法,可以通過(guò)alter修改schema
4、alter
使用方法:?
如 修改壓縮算法
但是需要執(zhí)行major_compact 'table'?命令之后 才會(huì)做實(shí)際的操作。
5、TTL
默認(rèn)是 2147483647 即:Integer.MAX_VALUE 值大概是68年?
這個(gè)參數(shù)是說(shuō)明該列族數(shù)據(jù)的存活時(shí)間,單位是s?
這個(gè)參數(shù)可以根據(jù)具體的需求對(duì)數(shù)據(jù)設(shè)定存活時(shí)間,超過(guò)存過(guò)時(shí)間的數(shù)據(jù)將在表中不在顯示,待下次major compact的時(shí)候再?gòu)氐讋h除數(shù)據(jù).?
注意的是TTL設(shè)定之后 MIN_VERSIONS=>’0’ 這樣設(shè)置之后,TTL時(shí)間戳過(guò)期后,將全部徹底刪除該family下所有的數(shù)據(jù),如果MIN_VERSIONS 不等于0那將保留最新的MIN_VERSIONS個(gè)版本的數(shù)據(jù),其它的全部刪除,比如MIN_VERSIONS=>’1’ 屆時(shí)將保留一個(gè)最新版本的數(shù)據(jù),其它版本的數(shù)據(jù)將不再保存。
6、describe ‘table’
這個(gè)命令查看了create table 的各項(xiàng)參數(shù)或者是默認(rèn)值。
7、disable_all ‘toplist.*’
disable_all 支持正則表達(dá)式,并列出當(dāng)前匹配的表的如下:?
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)? 并給出確認(rèn)提示.
8、drop_all
這個(gè)命令和disable_all的使用方式是一樣的
9、hbase 表預(yù)分區(qū)—-手動(dòng)分區(qū)
默認(rèn)情況下,在創(chuàng)建HBase表的時(shí)候會(huì)自動(dòng)創(chuàng)建一個(gè)region分區(qū),當(dāng)導(dǎo)入數(shù)據(jù)的時(shí)候,所有的HBase客戶端都向這一個(gè)region寫數(shù)據(jù),直到這個(gè)region足夠大了才進(jìn)行切分。一種可以加快批量寫入速度的方法是通過(guò)預(yù)先創(chuàng)建一些空的regions,這樣當(dāng)數(shù)據(jù)寫入HBase時(shí),會(huì)按照region分區(qū)情況,在集群內(nèi)做數(shù)據(jù)的負(fù)載均衡。?
命令方式:
也可以使用api的方式:
bin/hbase org.apache.hadoop.hbase.util.RegionSplitter test_table HexStringSplit -c 15 -f info參數(shù):
- test_table是表名
- HexStringSplit 是split 方式
- -c 是分15個(gè)region
- -f 是family
可在Web上查看結(jié)果,如圖:?
這樣就可以將表預(yù)先分為15個(gè)區(qū),減少數(shù)據(jù)達(dá)到storefile 大小的時(shí)候自動(dòng)分區(qū)的時(shí)間消耗,并且還有以一個(gè)優(yōu)勢(shì),就是合理設(shè)計(jì)rowkey 能讓各個(gè)region 的并發(fā)請(qǐng)求平均分配(趨于均勻) 使IO 效率達(dá)到最高,但是預(yù)分區(qū)需要將filesize 設(shè)置一個(gè)較大的值,hbase.hregion.max.filesize 這個(gè)值默認(rèn)是10G 也就是說(shuō)單個(gè)region 默認(rèn)大小是10G,?
這個(gè)參數(shù)的默認(rèn)值在0.90 到0.92到0.94.3各版本的變化:256M–1G–10G?
但是如果MapReduce Input類型為TableInputFormat 使用hbase作為輸入的時(shí)候,就要注意了,每個(gè)region一個(gè)map,如果數(shù)據(jù)小于10G 那只會(huì)啟用一個(gè)map 造成很大的資源浪費(fèi),這時(shí)候可以考慮適當(dāng)調(diào)小該參數(shù)的值,或者采用預(yù)分配region的方式,并將檢測(cè)如果達(dá)到這個(gè)值,再手動(dòng)分配region。
?
行鍵設(shè)計(jì)
表結(jié)構(gòu)設(shè)計(jì)
1、列族數(shù)量的設(shè)定
以用戶信息為例,可以將必須的基本信息存放在一個(gè)列族,而一些附加的額外信息可以放在另一列族;
2、行鍵的設(shè)計(jì)
語(yǔ)音詳單:?
13877889988-20150625?
13877889988-20150625?
13877889988-20150626?
13877889988-20150626?
—-將需要批量查詢的數(shù)據(jù)盡可能連續(xù)存放?
CMS系統(tǒng)—多條件查詢?
盡可能將查詢條件關(guān)鍵詞拼裝到rowkey中,查詢頻率最高的條件盡量往前靠?
20150230-zhangsan-category…?
20150230-lisi-category…?
Category+20150230 20150230-zhangsan-category?
(每一個(gè)條件的值長(zhǎng)度不同,可以通過(guò)做定長(zhǎng)映射來(lái)提高效率)
?
Hbase的設(shè)計(jì)原則
HBase是三維有序存儲(chǔ)的,通過(guò)rowkey(行鍵),column key(column family和qualifier)和TimeStamp(時(shí)間戳)這個(gè)三個(gè)維度可以對(duì)HBase中的數(shù)據(jù)進(jìn)行快速定位。
HBase中rowkey可以唯一標(biāo)識(shí)一行記錄,有以下3種查詢方式:
- 通過(guò)get方式,指定rowkey獲取唯一一條記錄
- 通過(guò)scan方式,設(shè)置startRow和stopRow參數(shù)進(jìn)行范圍匹配
- 全表掃描,即直接掃描整張表中所有行記錄
1、rowkey長(zhǎng)度原則
rowkey是一個(gè)二進(jìn)制碼流,可以是任意字符串,最大長(zhǎng)度64kb,實(shí)際應(yīng)用中一般為10-100bytes,以byte[]形式保存,一般設(shè)計(jì)成定長(zhǎng)。?
建議越短越好,不要超過(guò)16個(gè)字節(jié),原因如下:
- 數(shù)據(jù)的持久化文件HFile中是按照KeyValue存儲(chǔ)的,如果rowkey過(guò)長(zhǎng),比如超過(guò)100字節(jié),1000w行數(shù)據(jù),光rowkey就要占用100*1000w=10億個(gè)字節(jié),將近1G數(shù)據(jù),這樣會(huì)極大影響HFile的存儲(chǔ)效率;
- MemStore將緩存部分?jǐn)?shù)據(jù)到內(nèi)存,如果rowkey字段過(guò)長(zhǎng),內(nèi)存的有效利用率就會(huì)降低,系統(tǒng)不能緩存更多的數(shù)據(jù),這樣會(huì)降低檢索效率。
2、rowkey散列原則
如果rowkey按照時(shí)間戳的方式遞增,不要將時(shí)間放在二進(jìn)制碼的前面,建議將rowkey的高位作為散列字段,由程序隨機(jī)生成,低位放時(shí)間字段,這樣將提高數(shù)據(jù)均衡分布在每個(gè)RegionServer,以實(shí)現(xiàn)負(fù)載均衡的幾率。如果沒(méi)有散列字段,首字段直接是時(shí)間信息,所有的數(shù)據(jù)都會(huì)集中在一個(gè)RegionServer上,這樣在數(shù)據(jù)檢索的時(shí)候負(fù)載會(huì)集中在個(gè)別的RegionServer上,造成熱點(diǎn)問(wèn)題,會(huì)降低查詢效率。
3、rowkey唯一原則
必須在設(shè)計(jì)上保證其唯一性,rowkey是按照字典順序排序存儲(chǔ)的,因此,設(shè)計(jì)rowkey的時(shí)候,要充分利用這個(gè)排序的特點(diǎn),將經(jīng)常讀取的數(shù)據(jù)存儲(chǔ)到一塊,將最近可能會(huì)被訪問(wèn)的數(shù)據(jù)放到一塊。
?
熱點(diǎn)問(wèn)題
HBase中的行是按照rowkey的字典順序排序的,這種設(shè)計(jì)優(yōu)化了scan操作,可以將相關(guān)的行以及會(huì)被一起讀取的行存取在臨近位置,便于scan。然而糟糕的rowkey設(shè)計(jì)是熱點(diǎn)的源頭。
熱點(diǎn)發(fā)生在大量的client直接訪問(wèn)集群的一個(gè)或極少數(shù)個(gè)節(jié)點(diǎn)(訪問(wèn)可能是讀,寫或者其他操作)。大量訪問(wèn)會(huì)使熱點(diǎn)region所在的單個(gè)機(jī)器超出自身承受能力,引起性能下降甚至region不可用,這也會(huì)影響同一個(gè)RegionServer上的其他region,由于主機(jī)無(wú)法服務(wù)其他region的請(qǐng)求。
設(shè)計(jì)良好的數(shù)據(jù)訪問(wèn)模式以使集群被充分,均衡的利用。為了避免寫熱點(diǎn),設(shè)計(jì)rowkey使得不同行在同一個(gè)region,但是在更多數(shù)據(jù)情況下,數(shù)據(jù)應(yīng)該被寫入集群的多個(gè)region,而不是一個(gè)。
下面是一些常見(jiàn)的避免熱點(diǎn)的方法以及它們的優(yōu)缺點(diǎn)
1、加鹽
這里所說(shuō)的加鹽不是密碼學(xué)中的加鹽,而是在rowkey的前面增加隨機(jī)數(shù),具體就是給rowkey分配一個(gè)隨機(jī)前綴以使得它和之前的rowkey的開(kāi)頭不同。分配的前綴種類數(shù)量應(yīng)該和你想使用數(shù)據(jù)分散到不同的region的數(shù)量一致。加鹽之后的rowkey就會(huì)根據(jù)隨機(jī)生成的前綴分散到各個(gè)region上以避免熱點(diǎn)。
2、哈希
哈希會(huì)使同一行永遠(yuǎn)用一個(gè)前綴加鹽。哈希也可以使負(fù)載分散到整個(gè)集群,但是讀卻是可以預(yù)測(cè)的。使用確定的哈希可以讓客戶端重構(gòu)完整的rowkey,可以使用get操作準(zhǔn)確獲取某一個(gè)行數(shù)據(jù)。
3、反轉(zhuǎn)
第三種防止熱點(diǎn)的方法是反轉(zhuǎn)固定長(zhǎng)度或者數(shù)字格式的rowkey。這樣可以使得rowkey中經(jīng)常改變的部分(最沒(méi)有意義的部分)放在前面。這樣可以有效的隨機(jī)rowkey,但是犧牲了rowkey的有序性。
反轉(zhuǎn)rowkey的例子以手機(jī)號(hào)為rowkey,可以將手機(jī)號(hào)反轉(zhuǎn)后的字符串作為rowkey,這樣的就避免了以手機(jī)號(hào)那樣比較固定開(kāi)頭導(dǎo)致熱點(diǎn)問(wèn)題。
4、時(shí)間戳反轉(zhuǎn)
一個(gè)常見(jiàn)的數(shù)據(jù)處理問(wèn)題是快速獲取數(shù)據(jù)的最近版本,使用反轉(zhuǎn)的時(shí)間戳作為rowkey的一部分對(duì)這個(gè)問(wèn)題十分有用,可以用 Long.Max_Value - timestamp 追加到key的末尾,例如 [key][reverse_timestamp] , [key] 的最新值可以通過(guò)scan [key]獲得[key]的第一條記錄,因?yàn)镠Base中rowkey是有序的,第一條記錄是最后錄入的數(shù)據(jù)。
比如需要保存一個(gè)用戶的操作記錄,按照操作時(shí)間倒序排序,在設(shè)計(jì)rowkey的時(shí)候,可以這樣設(shè)計(jì):?
[userId反轉(zhuǎn)][Long.Max_Value - timestamp],在查詢用戶的所有操作記錄數(shù)據(jù)的時(shí)候,直接指定反轉(zhuǎn)后的userId,startRow是[userId反轉(zhuǎn)][000000000000],stopRow是[userId反轉(zhuǎn)][Long.Max_Value - timestamp]
如果需要查詢某段時(shí)間的操作記錄,startRow是[user反轉(zhuǎn)][Long.Max_Value - 起始時(shí)間],stopRow是[userId反轉(zhuǎn)][Long.Max_Value - 結(jié)束時(shí)間]
注意:?
盡量減少行和列的大小在HBase中,value永遠(yuǎn)和它的key一起傳輸?shù)摹.?dāng)具體的值在系統(tǒng)間傳輸時(shí),它的rowkey,列名,時(shí)間戳也會(huì)一起傳輸。如果你的rowkey和列名很大,甚至可以和具體的值相比較,那么你將會(huì)遇到一些有趣的問(wèn)題。HBase storefiles中的索引(有助于隨機(jī)訪問(wèn))最終占據(jù)了HBase分配的大量?jī)?nèi)存,因?yàn)榫唧w的值和它的key很大。可以增加block大小使得storefiles索引再更大的時(shí)間間隔增加,或者修改表的模式以減小rowkey和列名的大小。壓縮也有助于更大的索引。?
列族盡可能越短越好,最好是一個(gè)字符。?
冗長(zhǎng)的屬性名雖然可讀性好,但是更短的屬性名存儲(chǔ)在HBase中會(huì)更好。
總結(jié)
以上是生活随笔為你收集整理的Hbase高级应用:建表高级属性、行键设计、设计原则、热点问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Hbase寻址机制
- 下一篇: Spark算子:RDD创建操作