一、HBase關鍵參數配置指導
如果同時存在讀和寫的操作,這兩種操作的性能會相互影響。如果寫入導致的flush和Compaction操作頻繁發生,會占用大量的磁盤IO操作,從而影響讀取的性能。如果寫入導致阻塞較多的Compaction操作,就會出現Region中存在多個HFile的情況,從而影響讀取的性能。所以如果讀取的性能不理想的時候,也要考慮寫入的配置是否合理。
1、提升寫效率
1.1客戶端調優
1.1.1 AutoFlush
參數值:setAutoFlush
解析:
autoflush=false的原理是當客戶端提交delete或put請求時,將該請求在客戶端緩存,直到數據超過2M(hbase.client.write.buffer決定)或用戶執行了hbase.flushcommits()時才向regionserver提交請求。因此即使htable.pu()執行返回成功,也並非說明請求真的成功了。假如還沒有達到該緩存而client崩潰,該部分數據將由於未發送到regionserver而丟失。這對於零容忍的在線服務是不可接受的。
autoflush=true雖然會讓寫入速度下降2-3本,但是對於很多在線應用來說這都是必須打開的,也正是hbase為什么讓它默認為true的原因,每次請求都會發往regionserver,而regionserver接收到請求后第一件事情就是寫HLOG。因此對IO要求是非常高的,為了提高hbase的寫入速度應該盡可能地提高IO吞吐量,比如增加磁盤、使用raid卡、減少replication因子數等。
如何調優?
經驗設定:
setAutoFlush=false
1.1.2使用PutList方式提交請求
可以極大地提升寫性能
1.2 Memstore相關
當regionserver(以下簡稱為RS)收到一個寫請求,會將這個請求定位到某個特定的region。每一個region存儲了一系列的Row,每一個Row對應的數據分散在一個或多個ColumnFamily(以下簡稱為CF)。特定CF的數據都存儲在對應的store里面,而每個store都是由一個memstore和數個storefile組成。memstore存儲在RS的內存中,而storefile則存儲在HDFS上。當一個寫請求到達RS的時候,該請求對應的數據首先會被menstore存儲,直到達到一定的臨界條件,memstore里面的數據才會flush到storefile。
使用memstore的主要原因是為了使存儲在HDFS上的數據是有序的(按Row)。HDFS設計為順序讀寫的,已有的文件不能被修改。這就意味着,因為hbase收到的寫請求是無序的,所以如果直接將這些數據寫到HDFS上,以后再對文件里面的內二做排序就會是一件極其困難的事情;無序的數據存儲方式,又會大大影響后續的讀請求性能。為了解決這種問題,hbase會將最近的某些寫請求放到內存中(也就是memstore),並將這些數據在flush到storefile之前做好排序。
除了解決排序的問題,memstore還有其他好處,比如:
它能充當memcache的角色,緩存最近寫入的數據。鑒於新數據的訪問頻率和幾率都比舊數據高很多,這就大大的提高客戶端的讀效率。
注意:每個memstore每次刷新時,都會給CF生產一個storefile。
剩下讀取就非常容易了,hbase會檢查數據是否在memstore里面,否則就去storefile讀取,然后返回給客戶端。
1.2.1 根據memstore大小flush hfile
參數值:hbase.hregion.memstore.flush.size
參數解析:
在regionserver中,當寫操作內存中存在超過memstore.flush.size大小的memstore,則MemstoreFlusher就啟動flush操作將該memstore以hfile的形式寫入對應的store中。
如何調優?
默認:128M
A、如果Regionserver的內存充足,而且活躍Region數量也不是很多的時候,可以適當增大該值,可以減少compaction的次數,有助於提升系統性能。
B、這種flush產生的時候,並不是緊急的flush,flush操作可能會有一定延遲,在延遲期間,寫操作還可以進行,Memstore還會繼續增大,最大值 = “memstore.flush.size” * "hbase.hregion.memstore.block.multiplier"。
C、當超過最大值時,將會阻塞寫操作。適當增大“hbase.hregion.memstore.block.multiplier”可以減少阻塞,減少性能波動。
參數值:hbase.regionserver.global.memstore.size
參數解析:
RegionServer中,負責flush操作的是MemStoreFlusher線程。該線程定期檢查寫操作內存,當寫操作占用內存總量達到閾值,MemStoreFlusher將啟動flush操作,按照從大到小的順序,flush若干相對較大的memstore,直到所占用內存小於閾值。
閾值=“hbase.regionserver.global.memstore.size” * "hbase.regionserver.global.memstore,size.lower.limit" * "Hbase_HEAPSIZE"
如何調優?
默認:0.4
該配置與“hfile.block.cache.size”的和不能超過0.8,也就是寫和讀操作的內存不能超過HeapSize的80%,這樣可以保證除讀和寫以外其他操作的正常運行。
1.2.3 Flush前進行Compaction
參數值:hbase.hstore.blockingStoreFiles
參數解析:
在region flush前首先判斷file文件個數,是否大於hbase.hstore.blockingStoreFiles。如果大於需要先Compaction並且讓flush延時90s(這個參數可以通過hbase.hstore.blockingWaitTime進行配置),在延時過程中,將會繼續寫從而使得Memstore還會繼續增大超過閾值(“memstore.flush.size” * "hbase.hregion.memstore.block.multiplier"),導致寫操作阻塞。當完成Compaction后,可能就會產生大量寫入。這樣就導致性能激烈震盪。
如何調優?
默認:7
增加hbase.hstore.blockingStoreFiles,可以降低Block幾率。
1.3 內存相關
Hbase利用內存完成讀寫操作。提高Hbase內存可以有效提高Hbase性能。
1.3.1 GC參數
參數值:GC_OPTS
參數解析:
GC_OPTS主要需要調整HeapSize的大小和NewSize的大小。
HMaster:
- -Xms512M -Xmx1G -XX:NewSize=64M -XX:MaxNewSize=128M
RegionServer:
- -Xms4G -Xmx6G -XX:NewSize=64M -XX:MaxNewSize=128M
如何調優?
A、挑戰者HeapSize大小的時候,建議將Xms和Xmx設置成相同的值,這樣可以避免JVM動態調整HeapSize大小的時候影響性能。
B、調整NewSize大小的時候,建議把其設置為HeapSize大小的1/9
C、HMaster:當HBase集群規模越大、Region數量越多時,可以適當調大HMaster的GC_OPTS參數。
D、RegionServer:RegionServer需要的內存一般比HMaster要大。在內存充足的情況下,HeapSize可以相對設置大一些。
經驗設定:
主Hmaster的HeapSize為4G的時候,Hbase集群可以支持100000Region數的規模。根據經驗值,單個RegionServer的HeapSize不建議超過20G。
1.4 HFile相關
1.4.1文件同步sync
參數值:hbase.regionserver.hfile.durable.sync
參數解析:
控制HFfile文件在寫入到HDFS時的同步程度。如果為true,HDFS在把數據寫入到硬盤后才返回:如果為false,HDFS在把數據寫入OS的緩存后就返回。
如何調優?
默認為true
把該值設置為false比設為true時在寫入性能上會更優。
1.5 Compaction相關
1.5.1Compact文件大小閾值
參數值:hbase.regionserver.thread.compaction.throttle
參數解析:
控制一次Minor Compaction時,進行compaction的文件總大小的閾值。
如何調優?
默認:1.5G
Compaction時的文件總大小會影響這一次compaction的執行時間,如果太大,可能會阻塞其他的compaction或flush操作。
1.5.2 Compact文件個數閾值
參數值:hbase.hstore.compaction.min
參數解析:
當一個Store中文件超過該值時,會進行compact。
如何調優?
默認:3
適當增大該值,可以減少文件被重復執行compaction,但是如果過大,會導致Store中文件數過多而影響讀取的性能。
1.5.3 Compact文件數目
參數值:hbase.hstore.compaction.max
參數解析:
控制一次compaction操作時的文件數量的最大值。
如何調優?
默認:10
與“hbase.hstore.compaction.max.size”的作用基本相同,主要是控制一次compaction操作的時間不要太長。
1.5.4 Compact文件大小選擇
參數值:hbase.hstore.compaction.max.size
參數解析:
如果一個HFle文件的大小大於該值,那么Minor Compaction操作中不會選擇這個文件進行compaction操作,除非進行Major Compaction操作。
如何調優?
默認:2.5G
這個值可以防止較大的HFile參與Compaction操作。在禁止Major Compaction后,一個Store中可能存在幾個HFile,而不會合並成一個HFile,這樣不會對數據讀取造成太大的性能影響。
1.5.5 Major Compaction執行周期
參數值:hbase.hregion.majorcompaction
參數解析:由於執行 Major Compaction 會占用較多的系統資源,如果正在處於系統繁忙時期,會影響系統的性能 。
如何調優?
默認: 24 小時
A. 如果業務沒有較多的更新、刪除、回收過期數據空間時, 建議設置為 0,以禁止Major Compaction。
B. 如果必須要執行 Major Compaction,以回收更多的空間,可以適當增加該值,同時配置參數“hbase.offpeak.end.hour”和“hbase.offpeak.start.hour”以控制 Major Compaction 發生在業務空閑的時期。
1.6 HLog相關
RS 上有一個 Write-ahead Log (以下簡稱 WAL),數據會持續的默認寫到這個文件中。它包含了所有已經提交到 RS 的,已經保留在 memstore 中但是尚未 flush 到 storefile 的數據編輯歷史。
這些在 memstore 中的,尚未持久化的數據,在 RS 發生錯誤時我們需要借助它進行恢復,它能重現這些尚未持久化的數據的編輯軌跡。 .
當 WAL(Hlog)變得非常大時,重現它的記錄會花費非常多的時間。因此,我們需要限制WAL 的大小,當達到這個大小時,會觸發 memstore 的 flush。
當數據 flush 到磁盤后,WAL 的大小就會變小,因為我們不需要再保存這些已經完成持久化的數據編輯記錄。
1.6.1 文件同步sync
參數值:hbase.regionserver.wal.durable.sync
參數解析:
控制 HLog 文件在寫入到 HDFS 時的同步程度。如果為 true, HDFS 在把數據寫入到硬盤后才返回;如果為 false, HDFS 在把數據寫入 OS 的緩存后就返回。
如何調優?
把該值設置為 false 比 true 在寫入性能上會更優。
1.6.2 Hlog Flush條件
參數值:hbase.regionserver.maxlogs hbase.regionserver.hlog.blocksize
參數解析:
A、表示一個RegionServer上未進行Flush的Hlog的文件數量的閾值,如果大於該值,RegionServer會強制進行flush操作。
B、表示每個Hlog文件的最大大小。如果Hlog文件大小大於該值,就會滾動出一個新的Hlog,舊的將被禁用並歸檔。
如何調優?
這兩個參數共同決定了RegionServer中可以存在的未進行Flush的hlog數量。WAL的最大容量 = hbase.regionserver.maxlogs * hbase.regionserver.hlog.blocksize。當達到這個容量的時候,memstore flush就會被觸發。因此,你在調整memstore的設置的時候,你同樣需要調整這些值來適應那些編號。否則,WAL容量達到限制可能導致memstore flush的罪魁禍首,你專門配置memstore參數所增加的資源可能永遠無法被物盡其用。這個時候可以適當調整這兩個參數的大小。以避免出現這種強制flush的情況。
經驗設定:
hbase.regionserver.maxlogs:默認32,建議調整為100
hbase.regionserver.hlog.blocksize:默認64M,建議調整為128M
1.7 表設計相關
1.7.1壓縮算法
參數值:COMPRESSION
參數解析:配置數據的壓縮算法,這里的壓縮是HFile中block級別的壓縮。對於可以壓縮的數據,配置壓縮算法可以有效減少磁盤的IO,從而達到提高性能的目的。
如何優化?
默認:None
並非所有數據都可以進行有效的壓縮。例如一張圖片的數據,因為圖片一般已經是壓縮后的數據,所以壓縮效果有限。推薦使用SNAPPY,因為它有較好的Encoding / Decoding 速度和可以接受的壓縮率。
實例:create 'test_table',{NAME => 'cf1', COMPRESSION => 'SNAPPY'}
1.7.2 Block大小
參數值:BLOCKSIZE
參數解析:
配置HFile中block塊的大小,不同的block塊大小,可以影響HBase讀寫數據的效率。越大的block塊,配合壓縮算法,壓縮的效率就越好;但是由於HBase的讀取數據是以block塊為單位的,所以越大的block塊,對應隨機讀的情況,性能可能會比較差。
如何調優?
默認:64Kb
如果要提升寫入性能,一般擴大到128kb或者256kb,可以提升寫數據的效率,也不會影響太大的隨機讀性能。
實例:create 'test_table',{NAME => 'cf1', BLOCKSIZE => '32768'}
1.7.3 緩存內存
參數值:IN_MEMORY
參數解析:
配置這個表的數據有限緩存在內存中,這樣可以有效提升讀取的性能。
如何調優?
默認:false
對於一些小表,而且需要頻繁進行讀取操作的,可以設置此配置項
實例:create 'test_table',{NAME => 'cf1', IN_MEMORY => 'true'}
2、提升讀效率
2.1 客戶端調優
A、Scan數據時需要設置caching(一次從服務端讀取的記錄條數,默認是1),若使用默認值讀性能會降到極低。
B、當不需要讀一條數據所有列時,需要指定讀取的列,以減少網絡IO
C、只讀取Rowkey時,可以為Scan添加一個只讀取Rowkey的filter(FirstKeyOnlyFilter或者KeyOnlyFilter)。
D、在客戶端代碼中,可以設置caching和batch用來提升查詢效率。
例如:Scan.setCaching(caching);scan.setBatch(batch); 當 caching 和 batch 都為 1 的時候,我們要返回 10 行具有 20 列的記錄,就要進行 201 次 RPC, 因為每一列都作為一個單獨的 Result 來返回,這樣是我們不可以接受的(還有一次 RPC 是用來確認 scan 已經完成) 。
a) RPC 次數公式: RPCs = (Rows * Cols per Row) / Min(Cols per Row, Batch Size)/Scanner Caching
2.2 內存相關
Hbase利用內存完成讀寫操作。提高HBase內存可以有效提高HBase性能。
2.2.1 GC參數
參數值:GC_OPTS
參數解析:
GC_OPTS主要需要調整HeapSize的大小和NewSize的大小。
HMaster:
- -Xms512M -Xmx1G -XX:NewSize=64M -XX:MaxNewSize=128M
RegionServer:
- -Xms4G -Xmx6G -XX:NewSize=64M -XX:MaxNewSize=128M
如何調優?
A. 調整 HeapSize 大小的時候,建議將 Xms 和 Xmx 設置成相同的值,這樣可以避免 JVM動態調整 HeapSize 大小的時候影響性能。
B. 調整 NewSize 大小的時候,建議把其設置為 HeapSize 大小的 1/9。
C. HMaster:當 HBase 集群規模越大、 Region 數量越多時,可以適當調大 HMaster 的GC_OPTS 參數。
D. RegionServer: RegionServer 需要的內存一般比 HMaster 要大。在內存充足的情況下,HeapSize 可以相對設置大一些。
經驗設定:
主 HMaster 的 HeapSize 為 4G 的時候, HBase 集群可以支持 100000Region 數的規模。根據經驗值,單個 RegionServer 的 HeapSize 不建議超過 20GB
2.3 緩存相關
參數值:hfile.block.cache.size
參數解析:
HBase緩存區大小,主要影響查詢性能。根據查詢模式以及查詢記錄分布情況來解決緩存區的大小。
如何調優?
默認:0.25
如果采用隨機查詢使得緩存區的命中率較低,可以適當降低緩存區大小。
3、關鍵參數配置指導--案例
3.1 活躍Region對集群的影響
HBase在設計上,遵循了LSM-TREE的原理:寫數據階段,盡最大努力先將每一個Region的數據保留在內存(MemStore)中,等達到一定的閾值(默認為128M)之后,再 將這些數據固化(Flush)到文件(HFile)中,在這過程中,為了保證數據的安全性,通過將數據寫入到一個人日志文件(Hlog)中:
在當前時間段可能被寫入用戶數據的Region,稱作“活躍"Region”。
舉例:
如果一個用戶表的Region是按天划分的,那么,第一天的用戶數據,只會被寫入到第一天的Region中,則這些Region就是活躍的Region。此時,對於其它天的Region,都處於一種“空閑”的狀態。
集群中每一個物理節點的內存資源都是有限的,每一個Region的數據都是暫時先保留在內存中然后再固化到HFile文件中的,因此,我們需要控制一個時間段的活躍的Region數目。如果Region過多的話,會導致內存資源緊張,每一個Region在內存中的數據可能還沒有達到預先設置閾值的大小就被提前觸發Flush操作,這會導致Flush頻率升高,產生大量的小HFile(小文件過多會導致讀取性能的直線下降,也會加大Compaction的頻率和壓力)。相反活躍Region過少的話,也會導致並發度提升不上去,讀寫性能偏低。
如何設置最合理的活躍Region數目?
需要根據MemStore Flush的閾值大小,以及RegionServer堆內存的大小、預留MemStore空間的大小進行合理的計算。
如下列子可以說明這種計算方法:
經驗舉例:
假設分配給RegionServer堆內存的大小為8G,MemStore所占空間比例為40%,MemStore Flush的閾值大小為128M,則合理的活躍Region數目約為8*1024*0.4/128=26(個/節點)。
以用戶交易記錄表為例。每一條用戶交易記錄關聯一個USER_ID,也關聯一個確切的交易時間點。
如果我們在設計Key值的時候,采用“USER_ID+TIME”的格式,則划分Region的時候,一定會按照USER_ID的范圍划分的。對於任意一天的交易記錄,可能涉及到各個范圍內的USER_ID,即可能涉及到所有的Region,因此所有的Region都可能是活躍的,就會導致前面提到的那種活躍Region過多的問題,而且這種問題會隨着時間的持續而不斷惡化下去。
如果RowKey采用格式“DAY+USER_ID_TIME”的話,Region一定是按天划分的,那么,第N天的用戶交易記錄數據只會設計到第N天的Region,也只有這一天的Region是活躍的,這樣就有力的控制了活躍Region數目:
4、定位調優
4.1日志收集
日志分類介紹:
當前HBase的日志保存在/var/log/Bigdata/HBase和/var/log/Bigdata/audit/hbase目錄下,具體如下:
4、2調優定位
對於讀寫性能定位和調優,主要查看Regionserver的hbase-XXX-regionserver-XXX.log 運
行日志。
日志中是否出現過以下信息?
**Flush thread woke up with memory above low water.
日志中出現這個信息說明有部分寫過程出現過阻塞等待的現象,造成這個現象的原因是各個Region的Memstore使用的大小加起來超過了總的閾值,於是阻塞,並開始找一個Region進行Flush,,這個過程會需要消耗掉一段時間,通常來說造成這個的原因是單台Region server上的Region數太多了,因此單台Region server上最好不要放置過多的Region,一種調節方法是調大split的fileSize,這樣可以適當的減少Region數,但需要關注調整后讀性能的變化。
**delaying flush up to
當日志中出現這個信息時,可能會造成出現下面的現象,從而產生影響,這個通常是StoreFile太多造成的,通常可以調大點StoreFile個數的閾值。
**Blocking updates for
當日志中出現這個信息時,表示寫動作已被阻塞,造成這個現象的原因是memStore中使用的大小已超過其閾值的2倍,通常是由於上面的delaving flush up to 造成的,或者是region數太多造成的,或者是太多的Hlog造成的,這種情況下會造成很大的影響,如內存夠用的話,可以調大閾值,如果是其他原因,就對症下葯。
4、3、定位調優思路
針對HBase讀寫變慢的場景,可以按照如下思路進行定位、調優:
開始-->對比性能差距-->查看監控信息-->查看相關日志-->確定具體場景-->進行參數調優-->后續觀察
4.3.1通過客戶端程序,記錄寫入、讀取速度
在客戶端程序中,可以記錄HBase寫入/讀取速度,關注性能差距。或者,通過HMaster的頁面來查看各個RegionServer的RPC請求。
4.3.2查看HBase監控信息
Region的分裂、compaction、flush次數過多、flush耗時高、硬件資源搶占等眾多元素都會影響性能,因此,需要從Manager監控頁面中,查看各個RegionServer的各類監控指標,需要重點關注:RegionServer GC時間、RegionServer GC次數、節點CPU/內存利用率、Compaction的次數,Flush文件次數、Flush操作的平均耗時、Split次數等信息。
4.3.3查看相關日志
結合HBase的監控信息,查看RegionServer的運行日志。
4.3.4舉例
4.3.4.1背景說明
某個HBase測試集群,客戶端主要是put寫入操作,發現寫入性能較慢。只有一張hbase表t1,表結構簡單(一個cf,一個qualifier),建表時預分5個Region。
4.3.4.2性能差距比較
通過客戶端put對t1表put數據計算出,單節點寫入速度為416條/s左右。
4.3.4.3監控信息展示
發現各個RegionServer的flush次數較多
RegionServer的內存占用並不高
4.3.4.4日志分析定位
可以查看RegionServer的運行日志,發現Flush被延長90000ms字樣:
2016-04-22 02:35:33,820 | WARN | MemStoreFlusher.0 | Region
t1,04,1461259167461.b6e781003392195313a5ec8e39c6bf77. has too many store files;
delaying flush up to 90000ms |
org.apache.hadoop.hbase.regionserver.MemStoreFlusher.flushRegion(MemStoreFlusher.jav
a:448)
初步分析結論:在內存利用不高的情況下,仍然有過多的Flush操作,並且看到有的Flush被延遲。因此,主要根據1.2章節內容,對MemStore相關參數,進行調優。
4.3.4.5參數調整&測試
調整前的參數為:
hbase.regionserver.global.memstore.size=0.1
hbase.hstore.blockingStoreFiles=2
調整后的參數為:
hbase.regionserver.global.memstore.size=0.4
hbase.hstore.blockingStoreFiles=7
調整后,用同樣的客戶端對同一張表 t1 進行 put 寫入測試, 發現寫入性能得到提升, 單
節點處理性能達到 1280 條/s
4、4常見問題處理
4.4.1 OOM(內存溢出)
4.4.1.1問題現象
當運行bulkload任務或開啟Region操作時,在RegionServer端產生如下的日志:
“java.lang.OutOfMemoryError:Direct buffer memory”
4.4.1.2問題定位過程
由於各種操作,HBase需要許多內存。I/O操作實驗direct buffer memory,因此為了更好的性能和提高並發數需要給RegionServer提供更多的direct buffer memory和heap memory。
檢查JVM參數,按照使用場景增加heap memory(-Xms/-Xmx)和direct buffer memory(-XX:MaxDirectMemorySize)
4.4.1.3問題解決方法
增加heap memory和direct buffer memory來避免OutOfMemory異常
eg:-Xms32G -Xmx32G -XX:MaxDirectMemorySize=2048M
經驗設定:
按照使用場景來修改GC_OPTS,RegionServer並發讀寫操作越多,需要的內存越大,經驗表明一般地上述示例配置能支撐單個RegionServer支持30個長期並發的需求。