天天看點

hbase 性能調優 一、服務端調優 二、Client端調優 ZK調優: hdf調優: 其它

轉載自 :hbase性能調優

一、服務端調優

 1、參數配置

   1)hbase.regionserver.handler.count:該設定決定了處理RPC的線程數量,預設值是10,通常可以調大,比如:150,當請求内容很大(上MB,比如大的put、使用緩存的scans)的時候,如果該值設定過大則會占用過多的記憶體,導緻頻繁的GC,或者出現OutOfMemory,是以該值不是越大越好。

  2)hbase.hregion.max.filesize:配置region大小,0.94.12版本預設是10G,region大小一般控制在幾個G比較合适,可以在建表時規劃好region數量,進行預分區,做到一定時間内,每個region的資料大小在一定的資料量之下,當發現有大的region,或者需要對整個表進行region擴充時再進行split操作,一般提供線上服務的hbase叢集均會棄用hbase的自動split,轉而自己管理split。

  3)hbase.hregion.majorcompaction:配置major合并的間隔時間,預設為1天,可設定為0,禁止自動的major合并,可手動或者通過腳本定期進行major合并,有兩種compact:minor和major,minor通常會把數個小的相鄰的storeFile合并成一個大的storeFile,minor不會删除标示為删除的資料和過期的資料,major會删除需删除的資料,major合并之後,一個store隻有一個storeFile檔案,會對store的所有資料進行重寫,有較大的性能消耗。

  4)hbase.hstore.compactionThreshold:HStore的storeFile數量>= compactionThreshold配置的值,則可能會進行compact,預設值為3,可以調大,比如設定為4,在定期的major compact中進行剩下檔案的合并,減少合并的次數,不過後果是會影響查詢的性能。

  5) hbase.hstore.blockingStoreFiles:HStore的storeFile的檔案數大于配置值,則在flush memstore前先進行split或者compact,除非超過hbase.hstore.blockingWaitTime配置的時間,預設為7,可調大,比如:100,避免memstore不及時flush,當寫入量大時,觸發memstore的block,進而阻塞寫操作。

  6)hbase.regionserver.global.memstore.upperLimit:預設值0.4,RS所有memstore占用記憶體在總記憶體中的upper比例,當達到該值,則會從整個RS中找出最需要flush的region進行flush,直到總記憶體比例降至該數限制以下,并且在降至限制比例以下前将阻塞所有的寫memstore的操作,在以寫為主的叢集中,可以調大該配置項,不建議太大,因為block cache和memstore cache的總大小不會超過0.8,而且不建議這兩個cache的大小總和達到或者接近0.8,避免OOM,在偏向寫的業務時,可配置為0.45,memstore.lowerLimit保持0.35不變,在偏向讀的業務中,可調低為0.35,同時memstore.lowerLimit調低為0.3,或者再向下0.05個點,不能太低,除非隻有很小的寫入操作,如果是兼顧讀寫,則采用預設值即可。

  7)hbase.regionserver.global.memstore.lowerLimit:預設值0.35,RS的所有memstore占用記憶體在總記憶體中的lower比例,當達到該值,則會從整個RS中找出最需要flush的region進行flush,配置時需結合memstore.upperLimit和block cache的配置。

  8)file.block.cache.size:RS的block cache的記憶體大小限制,預設值0.25,在偏向讀的業務中,可以适當調大該值,具體配置時需試hbase叢集服務的業務特征,結合memstore的記憶體占比進行綜合考慮。

  9)hbase.hregion.memstore.flush.size:預設值128M,機關位元組,超過将被flush到hdfs,該值比較适中,一般不需要調整。

  10)hbase.hregion.memstore.block.multiplier:預設值2,如果memstore的記憶體大小已經超過了hbase.hregion.memstore.flush.size的2倍,則會阻塞memstore的寫操作,直到降至該值以下,為避免發生阻塞,最好調大該值,比如:4,不可太大,如果太大,則會增大導緻整個RS的memstore記憶體超過memstore.upperLimit限制的可能性,進而增大阻塞整個RS的寫的幾率。如果region發生了阻塞會導緻大量的線程被阻塞在到該region上,進而其它region的線程數會下降,影響整體的RS服務能力,例如:

開始阻塞:

hbase 性能調優 一、服務端調優 二、Client端調優 ZK調優: hdf調優: 其它

 解開阻塞:

hbase 性能調優 一、服務端調優 二、Client端調優 ZK調優: hdf調優: 其它

 從10分11秒開始阻塞到10分20秒解開,總耗時9秒,在這9秒中無法寫入,并且這期間可能會占用大量的RS handler線程,用于其它region或者操作的線程數會逐漸減少,進而影響到整體的性能,也可以通過異步寫,并限制寫的速度,避免出現阻塞。

  11)hfile.block.index.cacheonwrite:在index寫入的時候允許put無根(non-root)的多級索引塊到block cache裡,預設是false,設定為true,或許讀性能更好,但是是否有副作用還需調查。

  12)hbase.regionserver.regionSplitLimit:控制最大的region數量,超過則不可以進行split操作,預設是Integer.MAX,可設定為1,禁止自動的split,通過人工,或者寫腳本在叢集空閑時執行。如果不禁止自動的split,則當region大小超過hbase.hregion.max.filesize時會觸發split操作(具體的split有一定的政策,不僅僅通過該參數控制,前期的split會考慮region資料量和memstore大小),每次flush或者compact之後,regionserver都會檢查是否需要Split,split會先下線老region再上線split後的region,該過程會很快,但是會存在兩個問題:1、老region下線後,新region上線前client通路會失敗,在重試過程中會成功但是如果是提供實時服務的系統則響應時長會增加;2、split後的compact是一個比較耗資源的動作。

  13)dfs.client.read.shortcircuit:開啟本地讀,hdfs預設是先寫本機,再寫其它dn,如果禁止hbase的split和balance,則可完全發揮本地讀的功效,如果不禁止也可以通過定期的major compact把分散的storefile合并成一個寫到本機的dn,參看:http://abloz.com/hbase/book.html的11.11.2章節。

  14)hbase.regionserver.maxlogs和hbase.regionserver.hlog.blocksize,參考16)

  15)Jvm調整:

       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"。

2 其它調優

  1)列族、rowkey要盡量短,每個cell值均會存儲一次列族名稱和rowkey,甚至列名稱也要盡量短,以下截圖是表test2的資料和存入hdfs後的檔案内容:

hbase 性能調優 一、服務端調優 二、Client端調優 ZK調優: hdf調優: 其它
hbase 性能調優 一、服務端調優 二、Client端調優 ZK調優: hdf調優: 其它

 由上圖可見:短的列族名稱、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,優化讀性能。

二、Client端調優

  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,也需要調優:

ZK調優:

  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,應根據叢集規模進行調整。

hdf調優:

  1、dfs.name.dir: namenode的資料存放位址,可以配置多個,位于不同的磁盤并配置一個NFS遠端檔案系統,這樣nn的資料可以有多個備份

  2、dfs.data.dir:dn資料存放位址,每個磁盤配置一個路徑,這樣可以大大提高并行讀寫的能力

  3、dfs.namenode.handler.count:nn節點RPC的處理線程數,預設為10,需提高,比如:60

  4、dfs.datanode.handler.count:dn節點RPC的處理線程數,預設為3,需提高,比如:20

  5、dfs.datanode.max.xcievers:dn同時處理檔案的上限,預設為256,需提高,比如:8192

  6、dfs.block.size:dn資料塊的大小,預設為64M,如果存儲的檔案均是比較大的檔案則可以考慮調大,比如,在使用hbase時,可以設定為128M,注意機關是位元組

  7、dfs.balance.bandwidthPerSec:在通過start-balancer.sh做負載均衡時控制傳輸檔案的速度,預設為1M/s,可配置為幾十M/s,比如:20M/s

  8、dfs.datanode.du.reserved:每塊磁盤保留的空餘空間,應預留一些給非hdfs檔案使用,預設值為0

  9、dfs.datanode.failed.volumes.tolerated:在啟動時會導緻dn挂掉的壞磁盤數量,預設為0,即有一個磁盤壞了,就挂掉dn,可以不調整。

其它

  設定作業系統的swappiness為0,則在實體記憶體不夠的情況下才會使用交換分區,避免GC回收時會花費更多的時間,當超過zk的session逾時時間則會出現rs當機的誤報,關于swappiness具體參考:http://en.wikipedia.org/wiki/Swappiness。