HBase優化相關


1.HBase預分區

HBase在創建表時,默認會自動創建一個Region分區。在導入數據時,所有客戶端都向這個Region寫數據,直到這個Region足夠大才進行切分。這樣在大量數據並行寫入時,容易引起單點負載過高,從而影響入庫性能。一個好的方法是在建立HBase表時預先分配數個Region,這樣寫入數據時,會按照Region分區情況,在集群內做數據的負載均衡。常用命令:

--自定義預分區的RowKey
hbase> create 't1', 'f1', SPLITS => ['10', '20', '30']
--使用文件內容預分區
hbase> create 't1', 'f1', SPLITS_FILE => 'splits.txt', OWNER => 'johndoe'
--使用內置的分區算法HexStringSplit
hbase> create 't1', 'f1', {NUMREGIONS => 3, SPLITALGO => 'HexStringSplit'}
--指定列族'info'使用'GZ'壓縮
hbase> create 'pre', { NAME => 'info', COMPRESSION => 'GZ'},  {NUMREGIONS =>3, SPLITS => ['10', '20']}

使用最后一個創建'pre'表,然后通過Web頁面 http://ncst:60010/table.jsp?name=pre 或者通過HBase shell命令scan 'hbase:meta' 查看hbase命名空間下所有標的元數據信息。 

 pre,,1442404691018.d514 column=info:regioninfo, timestamp=1442404691255, value={ENCODED => d
 e0dcd3d83aa48704d7f9a64 514e0dcd3d83aa48704d7f9a64db575, NAME => 'pre,,1442404691018.d514e0d
 db575.                  cd3d83aa48704d7f9a64db575.', STARTKEY => '', ENDKEY => '10'}        
 pre,10,1442404691018.50 column=info:regioninfo, timestamp=1442404691255, value={ENCODED => 5
 42efafeac5c9b6adce9868a 042efafeac5c9b6adce9868a9d0f72e, NAME => 'pre,10,1442404691018.5042e
 9d0f72e.                fafeac5c9b6adce9868a9d0f72e.', STARTKEY => '10', ENDKEY => '20'}    
 pre,20,1442404691018.81 column=info:regioninfo, timestamp=1442404691255, value={ENCODED => 8
 77de50218057a033be26c93 177de50218057a033be26c937c07be5, NAME => 'pre,20,1442404691018.8177d
 7c07be5.                e50218057a033be26c937c07be5.', STARTKEY => '20', ENDKEY => ''}      

可以看到第一個Region的 STARTKEY => '', ENDKEY => '10',第二個Region的 STARTKEY => '10', ENDKEY => '20',第三個Region的 STARTKEY => '20', ENDKEY => ''

需要注意的是: 

hbase> create 'pre', { NAME => 'info', COMPRESSION => 'GZ'},  {NUMREGIONS =>3, SPLITS => ['10', '20']}
--上述命令不等同於下面這條命令,並且下面這條命令還是錯誤的.
--這是因為【預分區】是針對整個Table,而不是某個Column Family
hbase> create 'pre', { NAME => 'info', COMPRESSION => 'GZ', NUMREGIONS =>3, SPLITS => ['10', '20']} 

2.hbase merge regions

對一個表進行預分區后,導入數據發現很多預分的region都沒有數據,預分的規則不太好,然后把那些沒有數據的region合並,使用hbase 有個merge工具。
用法hbase org.apache.hadoop.hbase.util.Merge <table_name> <region1> <region2>
具體寫法

//注意:執行該命令前需要停止hbase集群
hbase org.apache.hadoop.hbase.util.Merge pre pre,10,1442404691018.5042efafeac5c9b6adce9868a9d0f72e. pre,20,1442404691018.8177de50218057a033be26c937c07be5.

執行完后重新啟動集群,master:60010查看一下該表的regions,可以看到已經合並了。 

3.HBase的Bloom Filter

最根本的解釋:判斷一個元素是否屬於這個集合。Bloom Filter是一個很長的二進制向量和一系列隨機映射函數

如果這個集合中的元素足夠多,那么通過傳統遍歷的方法進行判斷耗時會很多。Bloom Filter就是一種利用很少的空間換取時間的實用方法。但是要說明的是:Bloom Filter的這種高效是有一定代價的,在判斷一個元素是否屬於某個集合時,有可能會把不屬於這個集合的元素誤認為屬於這個集合(誤判存在 false positive)。因此,Bloom Filter不適合那些“零錯誤”的應用場合。而在能容忍低錯誤率的應用場合下,Bloom Filter通過極少的錯誤換取了存儲空間的極大節省。

1.Bloom Filter的原理?

Bloom Filter是m位的數組,且這個數組的每一位都是零。

Step 1 映射:假如我們有A={x1,x2,x3….xn} n個元素,那么我們需要k個相互獨立的哈希Hash函數,將其中每個元素進行k次哈希,他們分別將這個元素映射到m位的數組中,而其映射的位置就置為1,如果有重復的元素映射到這個數組的同一個元素,那么這個元素只會記錄一次1,后續的映射將不會改變的這個元素的值。如圖:

Step 2 判斷:在判斷B={y1,y2} 這兩個元素是否屬於A集合時,我們就將這兩個元素分別進行上步映射中的k個哈希函數的哈希,如果結果全為1,那么就判斷屬於A集合,否則判斷其不屬於A集合。如下圖 y2屬於,y1則不屬於。

2.Bloom filter在HBase中的作用?
HBase利用Bloom filter來提高隨機讀(Get&Scan)的性能

3.Bloom filter在HBase中的開銷?
Bloom filter是一個列族(cf)級別的配置屬性,如果你在表中設置了Bloom filter,那么HBase會在生成StoreFile時包含一份bloomfilter結構的數據,稱其為MetaBlock;MetaBlock與DataBlock(真實的KeyValue數據)一起由LRUBlockCache維護。所以,開啟bloomfilter會有一定的存儲及內存cache開銷。

4.Bloom filter如何提高隨機讀的性能?
對於某個region的隨機讀,HBase會按照一定的順序遍歷每個memstore及storefile,將結果合並返回給客戶端。如果你設置了bloomfilter,那么在遍歷讀storefile時,就可以利用bloomfilter,忽略某些storefile。

5.HBase中的Bloom filter的類型及使用?
a). ROW行級過濾器, 根據KeyValue中的row來過濾storefile
  舉例:假設有2個storefile文件sf1和sf2,
  sf1包含kv1(r1 cf:q1 v)、kv2(r2 cf:q1 v)
  sf2包含kv3(r3 cf:q1 v)、kv4(r4 cf:q1 v)
  如果設置了CF屬性中的bloom filter為ROW,那么get(r1)時就會過濾sf1,get(r3)就會過濾sf2

b). ROWCOL行加列級過濾器,根據KeyValue中的row+qualifier來過濾storefile
  舉例:假設有2個storefile文件sf1和sf2,
  sf1包含kv1(r1 cf:q1 v)、kv2(r2 cf:q1 v)
  sf2包含kv3(r1 cf:q2 v)、kv4(r2 cf:q2 v)
  如果設置了CF屬性中的bloom filter為ROW,無論get(r1,q1)還是get(r1,q2),都會讀取sf1+sf2;而如果設置了CF屬性中的bloom filter為ROWCOL,那么get(r1,q1)就會過濾sf2,get(r1,q2)就會過濾sf1

6.ROWCOL一定比ROW效果好么?不一定
a). ROWCOL只對指定列(Qualifier)的隨機讀(Get)有效,如果應用中的隨機讀get,只含row,而沒有指定讀哪個qualifier,那么設置ROWCOL是沒有效果的,這種場景就應該使用ROW
b). 如果隨機讀中指定的列(Qualifier)的數目大於等於2,在0.90版本中ROWCOL是無效的,而在0.92版本以后,HBASE-2794對這一情景作了優化,是有效的(通過KeyValueScanner#seekExactly)
c). 如果同一row多個列的數據在應用上是同一時間put的,那么ROW與ROWCOL的效果近似相同,而ROWCOL只對指定了列的隨機讀才會有效,所以設置為ROW更佳

7.ROWCOL與ROW只在名稱上有聯系,ROWCOL並不是ROW的擴展,不能取代ROW

8.region下的storefile數目越多,bloom filter的效果越好

9.region下的storefile數目越少,HBase讀性能越好 

4.hbaseadmin.balancer()
用hbaseadmin.split()手動對region進行拆分,拆分完之后,每個子region並沒有均衡分布到3個regionserver上去。於是手工執行了一下hbaseadmin.balancer(),還是沒效果。
查看源碼發現原因:banancer()是針對整個集群的region分布,而不是針對某個表的region分布。它只保證每個regionserver上分布的regions在平均regions的0.8到1.2倍之間。

avg = 整個集群的總region數/regionserver個數
min = floor(avg*(1-0.2))
max=ceiling(avg*(1+0.2))

即所有regionserver上的regions個數都在min和max之間的話,就不會執行balancer。

補充說明:默認情況下是針對整個集群的region分布來均衡的,也可以針對表的region來均衡,需要配置:

<property>
<name>hbase.master.loadbalance.bytable</name>
<value>true</value>
</property>

然后重啟集群。再執行hbaseadmin.balancer()。可以發現分布在一個regionserver上的一個表的regions被均勻的分布在所有的regionserver上了。

5.hbase宕機處理 

HBase的RegionServer宕機超過一定時間后,HMaster會將其所管理的region重新分布到其他活動的RegionServer上,由於數據Store日志HLog都持久在HDFS中,該操作不會導致數據丟失。所以數據的一致性和安全性是有保障的。
但是重新分配的region需要根據日志HLog恢復原RegionServer中的內存MemoryStore表,這會導致宕機的region在這段時間內無法對外提供服務。
而一旦重分布,宕機的節點重新啟動后就相當於一個新的RegionServer加入集群,為了平衡,需要再次將某些Region分布到該server。  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM