一個系統(tǒng)上線之后督惰,開發(fā)和調(diào)優(yōu)將一直貫穿系統(tǒng)的生命周期中算柳,HBase也不列外。這里學習下HBase的調(diào)優(yōu)
Hbase查詢優(yōu)化
作為NoSQL數(shù)據(jù)庫旧蛾,增刪改查是其最基本的功能,其中查詢是最常用的一項芝硬。
設(shè)置Scan緩存
HBase中Scan查詢可以設(shè)置緩存蚜点,方法是setCaching()轧房,這樣可以有效的減少服務(wù)端與客戶端的交互拌阴,更有效的提升掃描查詢的性能。
/**
* Set the number of rows for caching that will be passed to scanners.
* If not set, the default setting from {@link HTable#getScannerCaching()} will apply.
* Higher caching values will enable faster scanners but will use more memory.
* @param caching the number of rows for caching
* 設(shè)置scanners緩存的行數(shù)
*/
public void setCaching(int caching) {
this.caching = caching;
}
顯示的指定列
當使用Scan或者GET獲取大量的行時奶镶,最好指定所需要的列迟赃,因為服務(wù)端通過網(wǎng)絡(luò)傳輸?shù)娇蛻舳耍瑪?shù)據(jù)量太大可能是瓶頸厂镇。如果能有效過濾部分數(shù)據(jù)纤壁,能很大程度的減少網(wǎng)絡(luò)I/O的花費。
/**
* Get all columns from the specified family.
* <p>
* Overrides previous calls to addColumn for this family.
* @param family family name
* @return this
* 獲取指定列簇的所有列
*/
public Scan addFamily(byte [] family) {
familyMap.remove(family);
familyMap.put(family, null);
return this;
}
/**
* Get the column from the specified family with the specified qualifier.
* <p>
* Overrides previous calls to addFamily for this family.
* @param family family name
* @param qualifier column qualifier
* @return this
* 獲取指定列簇的特定列
*/
public Scan addColumn(byte [] family, byte [] qualifier) {
NavigableSet<byte []> set = familyMap.get(family);
if(set == null) {
set = new TreeSet<byte []>(Bytes.BYTES_COMPARATOR);
}
if (qualifier == null) {
qualifier = HConstants.EMPTY_BYTE_ARRAY;
}
set.add(qualifier);
familyMap.put(family, set);
return this;
}
一般用:
scan.addColumn(...)
關(guān)閉ResultScanner
如果在使用table.getScanner之后捺信,忘記關(guān)閉該類酌媒,它會一直和服務(wù)端保持連接,資源無法釋放迄靠,從而導(dǎo)致服務(wù)端的某些資源不可用秒咨。
所以在用完之后,需要執(zhí)行關(guān)閉操作掌挚,這點與JDBS操作MySQL類似
scanner.close()
禁用塊緩存
如果批量進行全表掃描雨席,默認是有緩存的,如果此時有緩存吠式,會降低掃描的效率陡厘。
scan.setCacheBlocks(true|false);
對于經(jīng)常讀到的數(shù)據(jù),建議使用默認值特占,開啟塊緩存
緩存查詢結(jié)果
對于頻繁查詢HBase的應(yīng)用場景糙置,可以考慮在應(yīng)用程序和Hbase之間做一層緩存系統(tǒng),新的查詢先去緩存查是目,緩存沒有再去查Hbase罢低。
寫入優(yōu)化
寫也是Hbase常有的操作之一,并且Hbase在寫入操作上有著其他NoSQL無法比擬的優(yōu)勢,下面講如何優(yōu)化寫入操作
關(guān)閉寫WAL日志
一般為了保證系統(tǒng)的高可用性网持,WAL日志默認是開啟狀態(tài)宜岛,WAL主要用于災(zāi)難恢復(fù)的,如果應(yīng)用可以容忍一定的數(shù)據(jù)丟失風險功舀,可以在寫數(shù)據(jù)的時候萍倡,關(guān)閉寫WAL。
風險: 當RegionServer宕機時辟汰,寫入的數(shù)據(jù)出現(xiàn)丟失列敲,且無法恢復(fù)
設(shè)置AutoFlush
Htable有一個屬性是AutoFlush,該屬性用于支持客戶端的批量更新帖汞,默認是true戴而,當客戶端每收到一條數(shù)據(jù),立刻發(fā)送到服務(wù)端翩蘸,如果設(shè)置為false所意,當客戶端提交put請求時候,先將該請求在客戶端緩存催首,到達閾值的時候或者執(zhí)行hbase.flushcommits()扶踊,才向RegionServer提交請求。
風險 在請求未發(fā)送到RegionServer之前客戶端崩潰郎任,數(shù)據(jù)也會丟失
table.setAutoFlush(false);
table.setWriteBufferSize( 12 * 1024 * 1024 );
預(yù)創(chuàng)建Region
一般表剛開始只有一個Region秧耗,插入該表的數(shù)據(jù)都會保存在此Region中,插入該表的所有塑化劑都會保存在該Region中舶治,當?shù)竭_一定的閾值時分井,才發(fā)生分裂。 這樣開始時刻針對該表的寫操作都集中在某臺服務(wù)器上霉猛,造成這臺服務(wù)器的壓力很緊張尺锚,同時對整個集群資源的浪費
建議剛開始的時候預(yù)創(chuàng)建Region,可以使用Hbase自帶的RegionSplitter
延遲日志flush
默認寫入操作韩脏,首先寫入WAL缩麸,并且在1S內(nèi)寫入HDFS,這個時間默認是1S赡矢,可以通過參數(shù)配置
hbase.regionserver.optionallogflushinterval
可以配置大一點的值杭朱,比如5s,這段時間數(shù)據(jù)會保留在內(nèi)存中吹散,直到RegionServer周期性的執(zhí)行flush操作弧械。
最后
這里提供了一些讀寫優(yōu)化的參考,希望能幫助大家