您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關(guān)如何解決HBase Replication在數(shù)據(jù)大量寫入時(shí)導(dǎo)致RegionServer崩潰問題,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
HBase在0.90之后的版本提供Replication功能,這些天本人在測試這個(gè)功能時(shí)發(fā)現(xiàn)在大量數(shù)據(jù)(>100W)寫入時(shí)會(huì)出現(xiàn)RegionServer崩潰的情況。異常日志如下:
2014-10-29 10:40:44,225 WARN org.apache.hadoop.hdfs.DFSClient: DFSOutputStream ResponseProcessor exception for block blk_-2223802775658985697_1410java.io.EOFException at java.io.DataInputStream.readFully(DataInputStream.java:180) at java.io.DataInputStream.readLong(DataInputStream.java:399) at org.apache.hadoop.hdfs.protocol.DataTransferProtocol$PipelineAck.readFields(DataTransferProtocol.java:124) at org.apache.hadoop.hdfs.DFSClient$DFSOutputStream$ResponseProcessor.run(DFSClient.java:2967) 2014-10-29 10:40:44,225 INFO org.apache.hadoop.hdfs.DFSClient: Could not obtain block blk_-2223802775658985697_1410 from any node: java.io.IOException: No live nodes contain current block. Will get new block locations from namenode and retry... 2014-10-29 10:40:44,228 WARN org.apache.hadoop.hdfs.DFSClient: Error Recovery for block blk_-2223802775658985697_1410 bad datanode[0] 192.168.11.55:40010 2014-10-29 10:40:44,232 WARN org.apache.hadoop.hdfs.DFSClient: Error while syncing java.io.IOException: All datanodes 192.168.11.55:40010 are bad. Aborting... at org.apache.hadoop.hdfs.DFSClient$DFSOutputStream.processDatanodeError(DFSClient.java:3096) at org.apache.hadoop.hdfs.DFSClient$DFSOutputStream.access$2100(DFSClient.java:2589) at org.apache.hadoop.hdfs.DFSClient$DFSOutputStream$DataStreamer.run(DFSClient.java:2793) 2014-10-29 10:40:44,235 FATAL org.apache.hadoop.hbase.regionserver.wal.HLog: Could not sync. Requesting close of hlog java.io.IOException: Reflection at org.apache.hadoop.hbase.regionserver.wal.SequenceFileLogWriter.sync(SequenceFileLogWriter.java:310) at org.apache.hadoop.hbase.regionserver.wal.HLog.syncer(HLog.java:1366) at org.apache.hadoop.hbase.regionserver.wal.HLog.sync(HLog.java:1476) at org.apache.hadoop.hbase.regionserver.HRegion.syncOrDefer(HRegion.java:5970) at org.apache.hadoop.hbase.regionserver.HRegion.doMiniBatchMutation(HRegion.java:2490) at org.apache.hadoop.hbase.regionserver.HRegion.batchMutate(HRegion.java:2190) at org.apache.hadoop.hbase.regionserver.HRegionServer.multi(HRegionServer.java:3888) at sun.reflect.GeneratedMethodAccessor33.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.hadoop.hbase.ipc.WritableRpcEngine$Server.call(WritableRpcEngine.java:323) at org.apache.hadoop.hbase.ipc.HBaseServer$Handler.run(HBaseServer.java:1434) Caused by: java.lang.reflect.InvocationTargetException at sun.reflect.GeneratedMethodAccessor35.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.hadoop.hbase.regionserver.wal.SequenceFileLogWriter.sync(SequenceFileLogWriter.java:308) ... 11 more Caused by: java.io.IOException: DFSOutputStream is closed at org.apache.hadoop.hdfs.DFSClient$DFSOutputStream.sync(DFSClient.java:3669) at org.apache.hadoop.fs.FSDataOutputStream.sync(FSDataOutputStream.java:97) at org.apache.hadoop.io.SequenceFile$Writer.syncFs(SequenceFile.java:995) ... 15 more
實(shí)際上,這個(gè)問題并不是由Replication功能引起的,而由客戶端在數(shù)據(jù)密集寫入時(shí)超時(shí)引起的
============================以下內(nèi)容來源于網(wǎng)絡(luò)===================================
正常情況下DFSClient寫block數(shù)據(jù)的過程是:
1. DFSClient端
a)DFSOutputStream負(fù)責(zé)數(shù)據(jù)的接收和寫入,即通過DFSOutputSummer中的write方法(synchronized)獲得數(shù)據(jù),而sync(主要代碼 synchronized(this))通過FlushBuffer建立packet后,通過enqueuePacket向dataQueue中寫入數(shù)據(jù)。
b)DFSOutputStream中的DataStreamer(Daemon線程),負(fù)責(zé)向DataNode發(fā)送數(shù)據(jù),每次發(fā)送前會(huì)檢查dataQueue中是否有數(shù)據(jù),沒有就等待。
c)DataStreamer建立pipeline傳輸數(shù)據(jù)時(shí),對這個(gè)pipeline會(huì)起一個(gè)ResponseProcessor(Thread)去獲得DataNode的反饋ack,并判斷是否有錯(cuò)誤、進(jìn)行recoverBlock等
2. DataNode端
a)在每個(gè)packet傳輸過程中,根據(jù)建立數(shù)據(jù)傳輸?shù)膒ipleLine,上游依次向下游發(fā)送數(shù)據(jù),下游依次向上游發(fā)送ack。
b)pipeline的最后一個(gè)節(jié)點(diǎn)(numTarget=0),PacketResponder 會(huì)一直運(yùn)行l(wèi)astDatanodeRun?方法,這個(gè)方法會(huì)在ack發(fā)送完畢(ackQueue.size()=0)后約1/2個(gè)dfs.socket.timeout?時(shí)刻發(fā)送心跳包,沿著pipeline發(fā)送給client。
3. HBase端
HBase端通過hlog中的writer向hdfs寫數(shù)據(jù),每次有數(shù)據(jù)寫入,都會(huì)sync。同時(shí),HLog中有個(gè)logSyncer,默認(rèn)配置是每秒鐘調(diào)用一次sync,不管有沒有數(shù)據(jù)寫入。
這個(gè)問題首先是由于超時(shí)引起的,我們先分析一下超時(shí)前后DFSClient和DataNode上發(fā)生了什么。
1. 問題重現(xiàn)
a)客戶端ResponseProcessor報(bào)69秒socket超時(shí),出錯(cuò)點(diǎn)在PipelineAck.readFields()。出錯(cuò)后直接catch,標(biāo)記hasError=true,closed=true。這個(gè)線程不會(huì)停止。
b)DataStreamer在輪詢中調(diào)用processDatanodeError對hasError=true進(jìn)行處理。此時(shí)errorIndex=0(默認(rèn)值),首先會(huì)拋出Recovery for Block的異常. 然后關(guān)閉blockstream,重新基于兩個(gè)節(jié)點(diǎn)的pipeline進(jìn)行recoverBlock。
c)在DataNode上,processDatanodeError()關(guān)閉blockstream。這將導(dǎo)致pipeline中的packetResponder被interrupted和terminated。
d)在DataNode上,processDatanodeError()關(guān)閉blockstream,導(dǎo)致BlockReceiver的readNextPacket()中的readToBuf讀取不到數(shù)據(jù),throw EOFException的異常。這個(gè)異常一直向上拋,直到DataXceiver的run中,它將導(dǎo)致DataXceiver中止運(yùn)行,提示DataNode.dnRegistration Error。
e)recoverBlock會(huì)正常進(jìn)行,并先在兩個(gè)節(jié)點(diǎn)上完成(第二個(gè)和第三個(gè))。隨后Namenode會(huì)發(fā)現(xiàn)replicas數(shù)量不足,向DataNode發(fā)起transfer block的命令,這是一個(gè)異步的過程。但是在hlog檢查時(shí),transfer很有可能未完成,這時(shí)會(huì)報(bào) pipeline error detected. Found 2 replicas but expecting 3 replicas。并關(guān)閉hlog。
以上就是根據(jù)日志可以看到的錯(cuò)誤過程。
2. 問題分析
a)為什么會(huì)超時(shí),為什么心跳包沒有發(fā)?
根據(jù)以上的分析,ResponseProcessor socket 69秒超時(shí)是導(dǎo)致后續(xù)一系列異常和hlog關(guān)閉的原因。那么為何會(huì)發(fā)生socket超時(shí)?ResponseProcessor應(yīng)該會(huì)在dfs.socket.timeout的1/2時(shí)間內(nèi)收到HeartBeat包。
經(jīng)過打印日志,我們發(fā)現(xiàn),DataNode上配置的dfs.socket.timeout為180秒,而HBase調(diào)用DFSClient時(shí)采用默認(rèn)配置,即60秒。因此,DFSClient認(rèn)為超時(shí)時(shí)間為3×nodes.length+60=69秒,而DataNode端發(fā)送心跳包的timeout=1/2×180=90秒!因此,如果在沒有數(shù)據(jù)寫入的情況下,DataNode將在90秒后發(fā)送心跳包,此時(shí)DFSClient已經(jīng)socketTimeout了,并導(dǎo)致后續(xù)的一系列現(xiàn)象。
b)為什么會(huì)在69秒內(nèi)沒有新的packet發(fā)送過去呢?
我們先分析一下DFSOutputStream寫數(shù)據(jù)和sync的同步關(guān)系。DFSOutputStream繼承自FSOutputSummer,DFSOutputStream接收數(shù)據(jù)是通過FSOutputSummer的write方法,這個(gè)方法是synchronized。而sync方法的flushBuffer()和enqueuePacket(),也在synchronized(this)代碼塊中。也就是說,對一個(gè)DFSOutputStream線程,如果sync和write同時(shí)調(diào)用,將發(fā)生同步等待。在HBase的場景下,sync發(fā)生的頻率非常高,sync搶到鎖的可能性很大。這樣,就很有可能在不斷的sync,不斷的flushBuffer,但是卻沒能通過write寫入數(shù)據(jù)(被blocked了)。這就是導(dǎo)致超時(shí)時(shí)間內(nèi)一直沒有packet發(fā)送的原因。
綜上,HBase業(yè)務(wù)調(diào)用的特點(diǎn)和DFSOutputStream的synchronized代碼塊,很有可能69秒中沒有packet寫入。但這個(gè)時(shí)候,不應(yīng)該socket超時(shí),socket超時(shí)是這個(gè)問題的根本原因,而socket超時(shí)的原因是配置不一致。
3. 問題解決
在hdfs端和HBase端,給dfs.socket.timeout設(shè)置一個(gè)較大的值,比如300000(300秒)
以上就是如何解決HBase Replication在數(shù)據(jù)大量寫入時(shí)導(dǎo)致RegionServer崩潰問題,小編相信有部分知識點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見到或用到的。希望你能通過這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。