您好,登錄后才能下訂單哦!
這篇文章主要介紹HBase如何實現性能調優,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
節點下線
你可以在HBase的特定的節點上運行下面的腳本來停止RegionServer:
$ ./bin/hbase-daemon.sh stop regionserver
RegionServer會首先關閉所有的region然后把它自己關閉,在停止的過程中,RegionServer的會向Zookeeper報告說他已經過期了。master會發現RegionServer已經死了,會把它當作崩潰的server來處理。他會將region分配到其他的節點上去。
在下線節點之前要停止Load Balancer
如果在運行load balancer的時候,一個節點要關閉, 則Load Balancer和Master的recovery可能會爭奪這個要下線的Regionserver。為了避免這個問題,先將load balancer停止,參見下面的 Load Balancer.
RegionServer下線有一個缺點就是其中的Region會有好一會離線。Regions是被按順序關閉的。如果一個server上有很多region,從第一個region會被下線,到最后一個region被關閉,并且Master確認他已經死了,該region才可以上線,整個過程要花很長時間。在HBase 0.90.2中,我們加入了一個功能,可以讓節點逐漸的擺脫他的負載,最后關閉。HBase 0.90.2加入了 graceful_stop.sh腳本,可以這樣用,
$ ./bin/graceful_stop.sh Usage: graceful_stop.sh [--config &conf-dir>] [--restart] [--reload] [--thrift] [--rest] &hostname> thrift If we should stop/start thrift before/after the hbase stop/start rest If we should stop/start rest before/after the hbase stop/start restart If we should restart after graceful stop reload Move offloaded regions back on to the stopped server debug Move offloaded regions back on to the stopped server hostname Hostname of server we are to stop
要下線一臺RegionServer可以這樣做
$ ./bin/graceful_stop.sh HOSTNAME
這里的HOSTNAME是你想要下線的RegionServer的host.
關于HOSTNAME 傳遞到graceful_stop.sh的HOSTNAME必須和hbase使用的hostname一致,hbase用它來區分RegionServers。可以用master的UI來檢查RegionServers的id。通常是hostname,也可能是FQDN。不管HBase使用的哪一個,你可以將它傳到 graceful_stop.sh腳本中去,目前他還不支持使用IP地址來推斷hostname。所以使用IP就會發現server不在運行,也沒有辦法下線了。
graceful_stop.sh 腳本會一個一個將region從RegionServer中移除出去,以減少改RegionServer的負載。他會先移除一個region,然后再將這個region安置到一個新的地方,再移除下一個,直到全部移除。最后graceful_stop.sh腳本會讓RegionServer stop.,Master會注意到RegionServer已經下線了,這個時候所有的region已經重新部署好。RegionServer就可以干干凈凈的結束,沒有WAL日志需要分割。
Load Balancer 當執行graceful_stop腳本的時候,要將Region Load Balancer關掉(否則balancer和下線腳本會在region部署的問題上存在沖突):
hbase(main):001:0> balance_switch false true 0 row(s) in 0.3590 seconds
上面是將balancer關掉,要想開啟:
hbase(main):001:0> balance_switch true false 0 row(s) in 0.3590 seconds
14.3.2. 依次重啟 你還可以讓這個腳本重啟一個RegionServer,不改變上面的Region的位置。要想保留數據的位置,你可以依次重啟(Rolling Restart),就像這樣:
$ for i in `cat conf/regionservers|sort`; do ./bin/graceful_stop.sh --restart --reload --debug $i; done &> /tmp/log.txt &
Tail /tmp/log.txt來看腳本的運行過程.上面的腳本只對RegionServer進行操作。要確認load balancer已經關掉。還需要在之前更新master。下面是一段依次重啟的偽腳本,你可以借鑒它:
確認你的版本,保證配置已經rsync到整個集群中。如果版本是0.90.2,需要打上HBASE-3744 和 HBASE-3756兩個補丁。
運行hbck確保你的集群是一致的
$ ./bin/hbase hbck
當發現不一致的時候,可以修復參考http://my.oschina.net/drl/blog/683885。
重啟Master:
$ ./bin/hbase-daemon.sh stop master; ./bin/hbase-daemon.sh start master
關閉region balancer:
$ echo "balance_switch false" | ./bin/hbase
在每個RegionServer上運行graceful_stop.sh:
$ for i in `cat conf/regionservers|sort`; do ./bin/graceful_stop.sh --restart --reload --debug $i; done &> /tmp/log.txt &
如果你在RegionServer還開起來thrift和rest server。還需要加上--thrift or --rest 選項 (參見 graceful_stop.sh 腳本的用法).
再次重啟Master.這會把已經死亡的server列表清空,重新開啟balancer.
運行 hbck 保證集群是一致的
zookeeper.session.timeout
默認值:3分鐘(180000ms)
說明:RegionServer與Zookeeper間的連接超時時間。當超時時間到后,ReigonServer會被Zookeeper從RS集群清單中移除,HMaster收到移除通知后,會對這臺server負責的regions重新balance,讓其他存活的RegionServer接管.
調優:這個timeout決定了RegionServer是否能夠及時的failover。設置成1分鐘或更低,可以減少因等待超時而被延長的failover時間。 不過需要注意的是,對于一些Online應用,RegionServer從宕機到恢復時間本身就很短的(網絡閃斷,crash等故障,運維可快速介入),如果調低timeout時間,反而會得不償失。因為當ReigonServer被正式從RS集群中移除時,HMaster就開始做balance了(讓其他RS根據故障機器記錄的WAL日志進行恢復)。當故障的RS在人工介入恢復后,這個balance動作是毫無意義的,反而會使負載不均勻,給RS帶來更多負擔。特別是那些固定分配regions的場景。
hbase.regionserver.handler.count
默認值:10
說明:RegionServer的請求處理IO線程數。
調優:這個參數的調優與內存息息相關。 較少的IO線程,適用于處理單次請求內存消耗較高的Big PUT場景(大容量單次PUT或設置了較大cache的scan,均屬于Big PUT)或ReigonServer的內存比較緊張的場景。 較多的IO線程,適用于單次請求內存消耗低,TPS要求非常高的場景。設置該值的時候,以監控內存為主要參考。 這里需要注意的是如果server的region數量很少,大量的請求都落在一個region上,因快速充滿memstore觸發flush導致的讀寫鎖會影響全局TPS,不是IO線程數越高越好。 壓測時,開啟Enabling RPC-level logging,可以同時監控每次請求的內存消耗和GC的狀況,最后通過多次壓測結果來合理調節IO線程數。 這里是一個案例?Hadoop and HBase Optimization for Read Intensive Search Applications,作者在SSD的機器上設置IO線程數為100,僅供參考。
hbase.hregion.max.filesize
默認值:256M
說明:在當前ReigonServer上單個Reigon的最大存儲空間,單個Region超過該值時,這個Region會被自動split成更小的region。
調優: 小region對split和compaction友好,因為拆分region或compact小region里的storefile速度很快,內存占用低。缺點是split和compaction會很頻繁。 特別是數量較多的小region不停地split, compaction,會導致集群響應時間波動很大,region數量太多不僅給管理上帶來麻煩,甚至會引發一些Hbase的bug。 一般512以下的都算小region。
大region,則不太適合經常split和compaction,因為做一次compact和split會產生較長時間的停頓,對應用的讀寫性能沖擊非常大。此外,大region意味著較大的storefile,compaction時對內存也是一個挑戰。 當然,大region也有其用武之地。如果你的應用場景中,某個時間點的訪問量較低,那么在此時做compact和split,既能順利完成split和compaction,又能保證絕大多數時間平穩的讀寫性能。
既然split和compaction如此影響性能,有沒有辦法去掉? compaction是無法避免的,split倒是可以從自動調整為手動。 只要通過將這個參數值調大到某個很難達到的值,比如100G,就可以間接禁用自動split(RegionServer不會對未到達100G的region做split)。 再配合RegionSplitter這個工具,在需要split時,手動split。 手動split在靈活性和穩定性上比起自動split要高很多,相反,管理成本增加不多,比較推薦online實時系統使用。
內存方面,小region在設置memstore的大小值上比較靈活,大region則過大過小都不行,過大會導致flush時app的IO wait增高,過小則因store file過多影響讀性能。
hbase.regionserver.global.memstore.upperLimit/lowerLimit
默認值:0.4/0.35
upperlimit說明:hbase.hregion.memstore.flush.size 這個參數的作用是當單個Region內所有的memstore大小總和超過指定值時,flush該region的所有memstore。RegionServer的flush是通過將請求添加一個隊列,模擬生產消費模式來異步處理的。那這里就有一個問題,當隊列來不及消費,產生大量積壓請求時,可能會導致內存陡增,最壞的情況是觸發OOM。 這個參數的作用是防止內存占用過大,當ReigonServer內所有region的memstores所占用內存總和達到heap的40%時,HBase會強制block所有的更新并flush這些region以釋放所有memstore占用的內存。
lowerLimit說明: 同upperLimit,只不過lowerLimit在所有region的memstores所占用內存達到Heap的35%時,不flush所有的memstore。它會找一個memstore內存占用最大的region,做個別flush,此時寫更新還是會被block。lowerLimit算是一個在所有region強制flush導致性能降低前的補救措施。在日志中,表現為 “** Flush thread woke up with memory above low water.”
調優:這是一個Heap內存保護參數,默認值已經能適用大多數場景。 參數調整會影響讀寫,如果寫的壓力大導致經常超過這個閥值,則調小讀緩存hfile.block.cache.size增大該閥值,或者Heap余量較多時,不修改讀緩存大小。 如果在高壓情況下,也沒超過這個閥值,那么建議你適當調小這個閥值再做壓測,確保觸發次數不要太多,然后還有較多Heap余量的時候,調大hfile.block.cache.size提高讀性能。 還有一種可能性是?hbase.hregion.memstore.flush.size保持不變,但RS維護了過多的region,要知道 region數量直接影響占用內存的大小。
hfile.block.cache.size
默認值:0.2
說明:storefile的讀緩存占用Heap的大小百分比,0.2表示20%。該值直接影響數據讀的性能。
調優:當然是越大越好,如果寫比讀少很多,開到0.4-0.5也沒問題。如果讀寫較均衡,0.3左右。如果寫比讀多,果斷默認吧。設置這個值的時候,你同時要參考?hbase.regionserver.global.memstore.upperLimit?,該值是memstore占heap的最大百分比,兩個參數一個影響讀,一個影響寫。如果兩值加起來超過80-90%,會有OOM的風險,謹慎設置。
hbase.hstore.blockingStoreFiles
默認值:7
說明:在flush時,當一個region中的Store(Coulmn Family)內有超過7個storefile時,則block所有的寫請求進行compaction,以減少storefile數量。 調優:block寫請求會嚴重影響當前regionServer的響應時間,但過多的storefile也會影響讀性能。從實際應用來看,為了獲取較平滑的響應時間,可將值設為無限大。如果能容忍響應時間出現較大的波峰波谷,那么默認或根據自身場景調整即可。
hbase.hregion.memstore.block.multiplier
默認值:2
說明:當一個region里的memstore占用內存大小超過hbase.hregion.memstore.flush.size兩倍的大小時,block該region的所有請求,進行flush,釋放內存。 雖然我們設置了region所占用的memstores總內存大小,比如64M,但想象一下,在最后63.9M的時候,我Put了一個200M的數據,此時memstore的大小會瞬間暴漲到超過預期的hbase.hregion.memstore.flush.size的幾倍。這個參數的作用是當memstore的大小增至超過hbase.hregion.memstore.flush.size 2倍時,block所有請求,遏制風險進一步擴大。
調優: 這個參數的默認值還是比較靠譜的。如果你預估你的正常應用場景(不包括異常)不會出現突發寫或寫的量可控,那么保持默認值即可。如果正常情況下,你的寫請求量就會經常暴長到正常的幾倍,那么你應該調大這個倍數并調整其他參數值,比如hfile.block.cache.size和hbase.regionserver.global.memstore.upperLimit/lowerLimit,以預留更多內存,防止HBase server OOM。
hbase.hregion.memstore.mslab.enabled
默認值:true
說明:減少因內存碎片導致的Full GC,提高整體性能。
調優:詳見 http://kenwublog.com/avoid-full-gc-in-hbase-using-arena-allocation
啟用LZO壓縮
LZO對比Hbase默認的GZip,前者性能較高,后者壓縮比較高,具體參見?Using LZO Compression 。對于想提高HBase讀寫性能的開發者,采用LZO是比較好的選擇。對于非常在乎存儲空間的開發者,則建議保持默認。
不要在一張表里定義太多的Column Family
Hbase目前不能良好的處理超過包含2-3個CF的表。因為某個CF在flush發生時,它鄰近的CF也會因關聯效應被觸發flush,最終導致系統產生更多IO。
批量導入
在批量導入數據到Hbase前,你可以通過預先創建regions,來平衡數據的負載。詳見?Table Creation: Pre-Creating Regions
避免CMS concurrent mode failure
HBase使用CMS GC。默認觸發GC的時機是當年老代內存達到90%的時候,這個百分比由 -XX:CMSInitiatingOccupancyFraction=N 這個參數來設置。concurrent mode failed發生在這樣一個場景: 當年老代內存達到90%的時候,CMS開始進行并發垃圾收集,于此同時,新生代還在迅速不斷地晉升對象到年老代。當年老代CMS還未完成并發標記時,年老代滿了,悲劇就發生了。CMS因為沒內存可用不得不暫停mark,并觸發一次stop the world(掛起所有jvm線程),然后采用單線程拷貝方式清理所有垃圾對象。這個過程會非常漫長。為了避免出現concurrent mode failed,建議讓GC在未到90%時,就觸發。
通過設置-XX:CMSInitiatingOccupancyFraction=N
這個百分比, 可以簡單的這么計算。如果你的hfile.block.cache.size 和hbase.regionserver.global.memstore.upperLimit 加起來有60%(默認),那么你可以設置 70-80,一般高10%左右差不多。
Hbase客戶端優化
AutoFlush
將HTable的setAutoFlush設為false,可以支持客戶端批量更新。即當Put填滿客戶端flush緩存時,才發送到服務端。 默認是true。
Scan Caching
scanner一次緩存多少數據來scan(從服務端一次抓多少數據回來scan)。 默認值是 1,一次只取一條。
Scan Attribute Selection
scan時建議指定需要的Column Family,減少通信量,否則scan操作默認會返回整個row的所有數據(所有Coulmn Family)。
Close ResultScanners
通過scan取完數據后,記得要關閉ResultScanner,否則RegionServer可能會出現問題(對應的Server資源無法釋放)。
Optimal Loading of Row Keys
當你scan一張表的時候,返回結果只需要row key(不需要CF, qualifier,values,timestaps)時,你可以在scan實例中添加一個filterList,并設置 MUST_PASS_ALL操作,filterList中add?FirstKeyOnlyFilter或KeyOnlyFilter。這樣可以減少網絡通信量。
Turn off WAL on Puts
當Put某些非重要數據時,你可以設置writeToWAL(false),來進一步提高寫性能。writeToWAL(false)會在Put時放棄寫WAL log。風險是,當RegionServer宕機時,可能你剛才Put的那些數據會丟失,且無法恢復。
啟用Bloom Filter
Bloom Filter通過空間換時間,提高讀操作性能。
major_compact 'testtable'
通常生產環境會關閉自動major_compact(配置文件中hbase.hregion.majorcompaction設 為0),選擇一個晚上用戶少的時間窗口手工major_compact,如果hbase更新不是太頻繁,可以一個星期對所有表做一次 major_compact,這個可以在做完一次major_compact后,觀看所有的storefile數量,如果storefile數量增加到 major_compact后的storefile的近二倍時,可以對所有表做一次major_compact,時間比較長,操作盡量避免高鋒期。
1,copytable方式
bin/hbase org.apache.hadoop.hbase.mapreduce.CopyTable --peer.adr=zookeeper1,zookeeper2,zookeeper3:/hbase 'testtable'
目前0.92之前的版本的不支持多版本的復制,0.94已經支持多個版本的復制。當然這個操作需要添加hbase目錄里的conf/mapred-site.xml,可以復制hadoop的過來。 2,Export/Import
bin/hbase org.apache.hadoop.hbase.mapreduce.Export testtable /user/testtable [versions] [starttime] [stoptime] bin/hbase org.apache.hadoop.hbase.mapreduce.Import testtable /user/testtable
跨版本的遷移,我覺得是一個不錯的選擇,而且copytable不支持多版本,而export支持多版本,比copytable更實用一些。 3,直接拷貝hdfs對應的文件
首先拷貝hdfs文件,如bin/hadoop distcp hdfs://srcnamenode:9000/hbase/testtable/ hdfs://distnamenode:9000/hbase/testtable/ 然后在目的hbase上執行bin/hbase org.jruby.Main bin/add_table.rb /hbase/testtable
生成meta信息后,重啟hbase 這個操作是簡單的方式,操作之前可以關閉hbase的寫入,執行flush所有表(上面有介紹),再distcp拷貝,如果hadoop版本不一致,可以用hftp接口的方式,我推薦使用這種方式,成本低
a、內存大小: master默認為1G,可增加到2G,regionserver默認1G,可調大到10G,或者更大,zk并不耗資源,可以不用調整,需要注意的是,調整了rs的內存大小后,需調整hbase.regionserver.maxlogs和hbase.regionserver.hlog.blocksize這兩個參數,WAL的最大值由hbase.regionserver.maxlogs * hbase.regionserver.hlog.blocksize決定(默認32*32M~=1G),一旦達到這個值,就會被觸發flush memstore,如果memstore的內存增大了,但是沒有調整這兩個參數,實際上對大量小文件沒有任何改進,調整策略:hbase.regionserver.hlog.blocksize * hbase.regionserver.maxlogs 設置為略大于hbase.regionserver.global.memstore.lowerLimit * HBASE_HEAPSIZE。
b、垃圾回收: export HBASE_OPTS="$HBASE_OPTS -Xms30720m -Xmx30720m -XX:NewSize=512m -XX:MaxPermSize=128m -XX:PermSize=128m -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSCompactAtFullCollection -XX:+ExplicitGCInvokesConcurrent -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:/usr/local/hbase-0.94.0/logs/gc-hbase.log"。
1)列族、rowkey要盡量短,每個cell值均會存儲一次列族名稱和rowkey,甚至列名稱也要盡量短
2)RS的region數量:一般每個RegionServer不要過1000,過多的region會導致產生較多的小文件,從而導致更多的compact,當有大量的超過5G的region并且RS總region數達到1000時,應該考慮擴容。
3)建表時: a、如果不需要多版本,則應設置version=1; b、 開啟lzo或者snappy壓縮,壓縮會消耗一定的CPU,但是,磁盤IO和網絡IO將獲得極大的改善,大致可以壓縮4~5倍; c、合理的設計rowkey,在設計rowkey時需充分的理解現有業務并合理預見未來業務,不合理的rowkey設計將導致極差的hbase操作性能; d、合理的規劃數據量,進行預分區,避免在表使用過程中的不斷split,并把數據的讀寫分散到不同的RS,充分的發揮集群的作用; e、列族名稱盡量短,比如:“f”,并且盡量只有一個列族; f、視場景開啟bloomfilter,優化讀性能。
1、hbase.client.write.buffer:寫緩存大小,默認為2M,推薦設置為6M,單位是字節,當然不是越大越好,如果太大,則占用的內存太多;
2、hbase.client.scanner.caching:scan緩存,默認為1,太小,可根據具體的業務特征進行配置,原則上不可太大,避免占用過多的client和rs的內存,一般最大幾百,如果一條數據太大,則應該設置一個較小的值,通常是設置業務需求的一次查詢的數據條數,比如:業務特點決定了一次最多50條,則可以設置為50
3、設置合理的超時時間和重試次數,具體的內容會在后續的blog中詳細講解。
4、client應用讀寫分離 讀和寫分離,位于不同的tomcat實例,數據先寫入redis隊列,再異步寫入hbase,如果寫失敗再回存redis隊列,先讀redis緩存的數據(如果有緩存,需要注意這里的redis緩存不是redis隊列),如果沒有讀到再讀hbase。 當hbase集群不可用,或者某個RS不可用時,因為HBase的重試次數和超時時間均比較大(為保證正常的業務訪問,不可能調整到比較小的值,如果一個RS掛了,一次讀或者寫,經過若干重試和超時可能會持續幾十秒,或者幾分鐘),所以一次操作可能會持續很長時間,導致tomcat線程被一個請求長時間占用,tomcat的線程數有限,會被快速占完,導致沒有空余線程做其它操作,讀寫分離后,寫由于采用先寫redis隊列,再異步寫hbase,因此不會出現tomcat線程被占滿的問題, 應用還可以提供寫服務,如果是充值等業務,則不會損失收入,并且讀服務出現tomcat線程被占滿的時間也會變長一些,如果運維介入及時,則讀服務影響也比較有限。
5、如果把org.apache.hadoop.hbase.client.HBaseAdmin配置為spring的bean,則需配置為懶加載,避免在啟動時鏈接hbase的Master失敗導致啟動失敗,從而無法進行一些降級操作。
6、Scan查詢編程優化:
1)調整caching; 2)如果是類似全表掃描這種查詢,或者定期的任務,則可以設置scan的setCacheBlocks為false,避免無用緩存; 3)關閉scanner,避免浪費客戶端和服務器的內存; 4)限定掃描范圍:指定列簇或者指定要查詢的列; 5)、如果只查詢rowkey時,則使用KeyOnlyFilter可大量減少網絡消耗;
7、對響應時間有嚴格要求的在線實時系統,可以通過封裝hbase client api,通過線程池執行get等操作,通過Future.get()設置超時時間,超過時間沒有返回則執行其它邏輯,實現快速失敗的效果。
作為hbase依賴的狀態協調者ZK和數據的存儲則HDFS,也需要調優:
1、zookeeper.session.timeout:默認值3分鐘,不可配置太短,避免session超時,hbase停止服務,線上生產環境由于配置為1分鐘,出現過2次該原因導致的hbase停止服務,也不可配置太長,如果太長,當rs掛掉,zk不能快速知道,從而導致master不能及時對region進行遷移。
2、zookeeper數量:至少5個節點。給每個zookeeper 1G左右的內存,最好有獨立的磁盤。 (獨立磁盤可以確保zookeeper不受影響).如果集群負載很重,不要把Zookeeper和RegionServer運行在同一臺機器上面。就像DataNodes 和 TaskTrackers一樣,只有超過半數的zk存在才會提供服務,比如:共5臺,則最多只運行掛2臺,配置4臺與3臺一樣,最多只運行掛1臺。
3、hbase.zookeeper.property.maxClientCnxns:zk的最大連接數,默認為300,應根據集群規模進行調整。
dfs.name.dir: namenode的數據存放地址,可以配置多個,位于不同的磁盤并配置一個NFS遠程文件系統,這樣nn的數據可以有多個備份
dfs.data.dir:dn數據存放地址,每個磁盤配置一個路徑,這樣可以大大提高并行讀寫的能力
dfs.namenode.handler.count:nn節點RPC的處理線程數,默認為10,需提高,比如:60
dfs.datanode.handler.count:dn節點RPC的處理線程數,默認為3,需提高,比如:20
dfs.datanode.max.xcievers:dn同時處理文件的上限,默認為256,需提高,比如:8192
dfs.block.size:dn數據塊的大小,默認為64M,如果存儲的文件均是比較大的文件則可以考慮調大,比如,在使用hbase時,可以設置為128M,注意單位是字節
dfs.balance.bandwidthPerSec:在通過start-balancer.sh做負載均衡時控制傳輸文件的速度,默認為1M/s,可配置為幾十M/s,比如:20M/s
dfs.datanode.du.reserved:每塊磁盤保留的空余空間,應預留一些給非hdfs文件使用,默認值為0
dfs.datanode.failed.volumes.tolerated:在啟動時會導致dn掛掉的壞磁盤數量,默認為0,即有一個磁盤壞了,就掛掉dn,可以不調整。
以上是“HBase如何實現性能調優”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。