1. 程式人生 > >解決hbase RegionServer頻繁宕機的一些辦法

解決hbase RegionServer頻繁宕機的一些辦法

HBase在使用中會遇到非常多的問題,最為常見的就是HBase regionserver掛掉(此文中簡稱regionserver為RS),

而RS掛掉的原因各不相同。在本文中對遇到過的HBase RS掛掉的情況做一個簡單的整理。
HBase叢集預留記憶體不足

現象:HBase RS在起來1-2min後馬上掛掉

日誌為如下日誌段的重複:

Mon Aug  6 10:23:54 CST 2018 Starting regionserver on node2.rosa.com

core file size          (blocks, -c) 0

data seg size           (kbytes, -d) unlimited

scheduling priority             (-e) 0

file size               (blocks, -f) unlimited

pending signals                 (-i) 127902

max locked memory       (kbytes, -l) 64

max memory size         (kbytes, -m) unlimited

open files                      (-n) 65536

pipe size            (512 bytes, -p) 8

POSIX message queues     (bytes, -q) 819200

real-time priority              (-r) 0

stack size              (kbytes, -s) 8192

cpu time               (seconds, -t) unlimited

max user processes              (-u) 2048

virtual memory          (kbytes, -v) unlimited

file locks                      (-x) unlimited

分析:此處可知所做的操作只是HBase RS的假啟動,前端看上去好像是啟動成功了,但是實際上並沒有真正啟動。

解決思路:適當減小HBase RegionServer Maximum Memory對應的值。

 
HBase叢集時鐘不同步

現象:HBase RS執行一段時間後掛掉

日誌:ERROR [B.defaultRpcServer.handler=4,queue=1,port=16000] master.MasterRpcServices: Region server slave1,16020,1494163890158 reported a fatal error:

ABORTING region server slave1,16020,1494163890158: Unhandled: org.apache.hadoop.HBase.ClockOutOfSyncException: Server slave1,16020,1494163890158 has been rejected; Reported time is too far out of sync with master.Time difference of 52782ms > max allowed of 30000ms

分析:叢集中的不同機器時間差較大,HBase叢集對時鐘同步要求較高。

解決思路:

    檢視叢集中/etc/ntp.conf的server配置是否合理,
    利用service ntpd status來檢視ntp的狀態
    利用service ntpd start啟動ntp
    利用ntpdate –u node1在三個節點立即進行時鐘同步
    利用chkconfig ntpd on設定所有節點ntp服務開機自啟動。

 
HBase叢集zk的連線數設定過少

現象:RS執行一段時間後掛掉

日誌:

ERROR [regionserver/node1/101.12.38.119:16020] zookeeper.ZooKeeperWatcher: regionserver:16020-0x3651eb7c95b0006, quorum=node1:2181,node2:2181,node3.hde.h3c.com:2181, baseZNode=/HBase-unsecure Received unexpected KeeperException, re-throwing exceptionorg.apache.zookeeper.KeeperException$SessionExpiredException: KeeperErrorCode = Session expired for /HBase-unsecure/replication/rs/node1,16020,1533819219139\

檢視zookeeper對應時間點的日誌:

2018-08-14 10:31:23,855 - WARN  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:[email protected]] - Too many connections from /101.12.38.120 - max is 60

2018-08-14 10:31:23,935 - WARN  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:[email protected]] - Too many connections from /101.12.38.120 - max is 60

2018-08-14 10:31:24,015 - WARN  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:[email protected]] - Too many connections from /101.12.38.120 - max is 60

2018-08-14 10:31:24,037 - WARN  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:[email protected]] - Too many connections from /101.12.38.120 - max is 60

2018-08-14 10:31:24,122 - WARN  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:[email protected]] - Too many connections from /101.12.38.120 - max is 60

2018-08-14 10:31:24,152 - WARN  [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:2181:[email protected]] - Too

      

分析:zookeeper的連線數設定過少,在HBase的高併發業務時會出現如上問題

解決思路:在zookeeper的配置檔案zoo.cfg中新增如下自定義配置(該配置在hbase中預設值為60):

新增:maxClientCnxns=600,重啟zk,啟動HBase。

 
HBase無法寫入(無法落地存到hdfs):

日誌:java.io.IOException: Failed to replace a bad datanode on the existing pipeline due to no more good datanodes being available to try

分析:無法寫入,3個datanode,備份數量設定的是3。在寫操作時,它會在pipeline中寫3個機器。預設replace-datanode-on-failure.policy是DEFAULT,如果系統中的datanode大於等於3,它會找另外一個datanode來拷貝。目前機器只有3臺,因此只要一臺datanode出問題,就一直無法寫入成功。

處理方法:

修改hdfs-site.xml檔案,新增或者修改如下兩項:

    <property>

        <name>dfs.client.block.write.replace-datanode-on-failure.enable</name>

         <value>true</value>

    </property>

 

    <property>

    <name>dfs.client.block.write.replace-datanode-on-failure.policy</name>

     <value>NEVER</value>

    </property>

 

    對於dfs.client.block.write.replace-datanode-on-failure.enable,客戶端在寫失敗的時候,是否使用更換策略,預設是true沒有問題

對於,dfs.client.block.write.replace-datanode-on-failure.policy,default在3個或以上備份的時候,是會嘗試更換結點嘗試寫入datanode。而在兩個備份的時候,不更換datanode,直接開始寫。對於3個datanode的叢集,只要一個節點沒響應寫入就會出問題,所以可以關掉。

 
HBase讀資料超時

日誌:ERROR org.apache.hadoop.hdfs.server.datanode.DataNode: xxx:50010:DataXceiver error processing WRITE_BLOCK operation  src: /xxx:52827 dst: /xxx:50010

java.net.SocketTimeoutException: 60000 millis timeout while waiting for channel to be ready for read. ch : java.nio.channels.SocketChannel[connected local=/xxx:50010 remote=/xxx:52827]

分析:讀資料超時,出現以上錯誤是因為datanode的服務執行緒連線數都被佔用,導致等待超時。

處理方法:

    datanode的資源情況適當增加的服務執行緒數:在hdfs-site.xml增加自定義配置檔案裡面新增或修改dfs.datanode.handler.count,預設是10,適當加大。
    增加客戶端的超時時間dfs.client.socket-timeout,預設是60000ms。
    增大HBase配置項中的zookeeper session timeout數值。
    增加DataNode max data transfer threads至合理數值。

 
HBase GC優化

報錯如下:

分析:

從以上日誌可以看出,session超時,其實服務是好的,只是被zk認為死了,所以rs自己也就把自己kill了。

值得注意的是此處的報錯,仍然不是深層次的原因,繼續檢視日誌:

2018-08-07 12:27:39,919 WARN  [regionserver/node1/210.26.111.41:16020] util.Sleeper: We slept 39000ms instead of 3000ms, this is likely due to a long garbage collecting pause and it's usually bad, see http://HBase.apache.org/book.html#trouble.rs.runtime.zkexpired

2018-08-07 12:27:39,920 INFO  [node1,16020,1533607130571_ChoreService_1] regionserver.HRegionServer$CompactionChecker: Chore: CompactionChecker missed its start time

2018-08-07 12:27:39,920 INFO  [main-SendThread(node2:2181)] zookeeper.ClientCnxn: Client session timed out, have not heard from server in 50201ms for sessionid 0x264ea4df477b894, closing socket connection and attempting reconnect

2018-08-07 12:27:39,920 WARN  [JvmPauseMonitor] util.JvmPauseMonitor: Detected pause in JVM or host machine (eg GC): pause of approximately 37173ms

GC pool 'ParNew' had collection(s): count=1 time=207ms

由以上日誌可見,HBase的put操作明視訊記憶體在Full GC的問題, 上文處的超時也由FULL GC引起。這種情況下,客戶端傳送的請求會受到阻塞,導致客戶端無法正常寫資料到HBase。

 

修改:

HBase寫優化方面:

    做HBase簡單的寫優化:增加HBase的write buffer至55%,減小HBase的read buffer至25%(write buffer與read buffer的和不能超過80%)
    增加HBase的regionserver handler數至最大。
    HBase表的預分割槽修改

Zk方面:

    HBase的zk超時檢測延長。

做完這些操作後現場未恢復正常,建議進行HBase的jvm調優如下:

會產生FULL GC的原因:老年代回收慢。

 

1.HBase堆記憶體

系統可以使用export HBASE_HEAPSIZE=16384,16G的記憶體,下是官網的一段話:

Thus, ~20-24Gb or less memory dedicated to one RS is recommended

2.GC的引數設定

HBASE jvm優化

export HBASE_OPTS="$HBASE_OPTS -XX:+UseCompressedOops -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0 -XX:+CMSParallelRemarkEnabled  -XX:CMSInitiatingOccupancyFraction=75 -XX:SoftRefLRUPolicyMSPerMB=0"

具體引數含義如下:

 

-XX:+UseCompressedOops

壓縮指標,解決記憶體佔用

 

-XX:+UseParNewGC

設定年輕代為並行收集

 

-XX:+UseConcMarkSweepG

使用CMS記憶體收集

 

-XX:+CMSClassUnloadingEnabled

相對於並行收集器,CMS收集器預設不會對永久代進行垃圾回收。如果希望對永久代進行垃圾回收,可用設定標誌-XX:+CMSClassUnloadingEnabled。 在早期JVM版本中,要求設定額外的標誌-XX:+CMSPermGenSweepingEnabled。注意,即使沒有設定這個標誌,一旦永久代耗盡空 間也會嘗試進行垃圾回收,但是收集不會是並行的,而再一次進行Full GC。

 

-XX:+UseCMSCompactAtFullCollection

使用併發收集器時,開啟對年老代的壓縮.

 

-XX:CMSFullGCsBeforeCompaction

由於併發收集器不對記憶體空間進行壓縮,整理,所以執行一段時間以後會產生”碎片”,使得執行效率降低.此值設定執行多少次GC以後對記憶體空間進行壓縮,整理.

 

-XX:+CMSParallelRemarkEnabled

降低標記停頓

 

-XX:CMSInitiatingOccupancyFraction=75

使用cms作為垃圾回收使用75%後開始CMS收集

 

-XX:SoftRefLRUPolicyMSPerMB

每兆堆空閒空間中SoftReference的存活時間