文档章节

解决HBase Replication在数据大量写入时导致RegionServer崩溃问题

liangtee
 liangtee
发布于 2014/10/29 12:40
字数 1420
阅读 5905
收藏 4
点赞 1
评论 0

HBase在0.90之后的版本提供Replication功能,这些天本人在测试这个功能时发现在大量数据(>100W)写入时会出现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


实际上,这个问题并不是由Replication功能引起的,而由客户端在数据密集写入时超时引起的

============================以下内容来源于网络===================================

正常情况下DFSClient写block数据的过程是:

1. DFSClient端
   a)DFSOutputStream负责数据的接收和写入,即通过DFSOutputSummer中的write方法(synchronized)获得数据,而sync(主要代码 synchronized(this))通过FlushBuffer建立packet后,通过enqueuePacket向dataQueue中写入数据。
   b)DFSOutputStream中的DataStreamer(Daemon线程),负责向DataNode发送数据,每次发送前会检查dataQueue中是否有数据,没有就等待。
   c)DataStreamer建立pipeline传输数据时,对这个pipeline会起一个ResponseProcessor(Thread)去获得DataNode的反馈ack,并判断是否有错误、进行recoverBlock等
2. DataNode端
   a)在每个packet传输过程中,根据建立数据传输的pipleLine,上游依次向下游发送数据,下游依次向上游发送ack。
   b)pipeline的最后一个节点(numTarget=0),PacketResponder 会一直运行lastDatanodeRun?方法,这个方法会在ack发送完毕(ackQueue.size()=0)后约1/2个dfs.socket.timeout?时刻发送心跳包,沿着pipeline发送给client。
3. HBase端
  HBase端通过hlog中的writer向hdfs写数据,每次有数据写入,都会sync。同时,HLog中有个logSyncer,默认配置是每秒钟调用一次sync,不管有没有数据写入。


这个问题首先是由于超时引起的,我们先分析一下超时前后DFSClient和DataNode上发生了什么。
1. 问题重现
    a)客户端ResponseProcessor报69秒socket超时,出错点在PipelineAck.readFields()。出错后直接catch,标记hasError=true,closed=true。这个线程不会停止。
    b)DataStreamer在轮询中调用processDatanodeError对hasError=true进行处理。此时errorIndex=0(默认值),首先会抛出Recovery for Block的异常. 然后关闭blockstream,重新基于两个节点的pipeline进行recoverBlock。
    c)在DataNode上,processDatanodeError()关闭blockstream。这将导致pipeline中的packetResponder被interrupted和terminated。
    d)在DataNode上,processDatanodeError()关闭blockstream,导致BlockReceiver的readNextPacket()中的readToBuf读取不到数据,throw EOFException的异常。这个异常一直向上抛,直到DataXceiver的run中,它将导致DataXceiver中止运行,提示DataNode.dnRegistration Error。
   e)recoverBlock会正常进行,并先在两个节点上完成(第二个和第三个)。随后Namenode会发现replicas数量不足,向DataNode发起transfer block的命令,这是一个异步的过程。但是在hlog检查时,transfer很有可能未完成,这时会报 pipeline error detected. Found 2 replicas but expecting 3 replicas。并关闭hlog。


以上就是根据日志可以看到的错误过程。
2. 问题分析
a)为什么会超时,为什么心跳包没有发?
根据以上的分析,ResponseProcessor socket 69秒超时是导致后续一系列异常和hlog关闭的原因。那么为何会发生socket超时?ResponseProcessor应该会在dfs.socket.timeout的1/2时间内收到HeartBeat包。
经过打印日志,我们发现,DataNode上配置的dfs.socket.timeout为180秒,而HBase调用DFSClient时采用默认配置,即60秒。因此,DFSClient认为超时时间为3×nodes.length+60=69秒,而DataNode端发送心跳包的timeout=1/2×180=90秒!因此,如果在没有数据写入的情况下,DataNode将在90秒后发送心跳包,此时DFSClient已经socketTimeout了,并导致后续的一系列现象。
b)为什么会在69秒内没有新的packet发送过去呢?
我们先分析一下DFSOutputStream写数据和sync的同步关系。DFSOutputStream继承自FSOutputSummer,DFSOutputStream接收数据是通过FSOutputSummer的write方法,这个方法是synchronized。而sync方法的flushBuffer()和enqueuePacket(),也在synchronized(this)代码块中。也就是说,对一个DFSOutputStream线程,如果sync和write同时调用,将发生同步等待。在HBase的场景下,sync发生的频率非常高,sync抢到锁的可能性很大。这样,就很有可能在不断的sync,不断的flushBuffer,但是却没能通过write写入数据(被blocked了)。这就是导致超时时间内一直没有packet发送的原因。

综上,HBase业务调用的特点和DFSOutputStream的synchronized代码块,很有可能69秒中没有packet写入。但这个时候,不应该socket超时,socket超时是这个问题的根本原因,而socket超时的原因是配置不一致。


3. 问题解决

在hdfs端和HBase端,给dfs.socket.timeout设置一个较大的值,比如300000(300秒)【注意两处设置的值要相等】

© 著作权归作者所有

共有 人打赏支持
liangtee
粉丝 104
博文 93
码字总数 38111
作品 0
朝阳
程序员
深入解读HBase2.0新功能之高可用读Region Replica

为什么需要Region Replica 在CAP理论中,HBase一直是一个CP(Consistency&Partition tolerance)系统。HBase一直以来都在遵循着读写强一致的语义。所以说虽然在存储层,HBase依赖HDFS实现了数...

HBase技术社区 ⋅ 06/07 ⋅ 0

HBase2.0中的新功能之Region Replica

前言 基于时间线一致的高可用读(Timeline-consistent High Available Reads),又称Region replica。其实早在HBase-1.2版本的时候,这个功能就已经开发完毕了,但是还是不太稳定,离生产可用...

正研 ⋅ 06/04 ⋅ 0

HBase运维基础――元数据逆向修复原理

  【IT168 评论】   背景   鉴于上次一篇文章――“云HBase小组成功抢救某公司自建HBase集群,挽救30+T数据”的读者反馈,对HBase的逆向工程比较感兴趣,并咨询如何使用相应工具进行运...

云栖社区 ⋅ 05/02 ⋅ 0

海量吞吐的实时NoSQL:HBase的七剑和双11圣战(数据脱敏版)

去年淘宝双11,作为媒体大屏(dataV)、消费记录、支付宝风控、物流详情、库存对账核心数据库的集团HBase,当天稳定运行,顺利完成了任务。并交出了非常漂亮的几项数据:QPS=1993W,TPS=3656W...

那珂 ⋅ 2016/05/30 ⋅ 0

分布式数据存储与管理[HDFS+HBase]

一、系统架构 在分布式存储领域,相信大多数人对HDFS(Hadoop Distributed File System)并不陌生,它是GFS(Google File System)的开源实现版本,解决大规模非结构化数据存储的问题。然而,...

u011459120 ⋅ 05/29 ⋅ 0

云HBase小组成功抢救某公司自建HBase集群,挽救30+T数据

摘要: 使用过开源HBase的人都知道,运维HBase是多么复杂的事情,集群大的时候,读写压力大,配置稍微不合理一点,就可能会出现集群状态不一致的情况,糟糕一点的直接导致入库、查询某个业务...

阿里云云栖社区 ⋅ 04/18 ⋅ 0

HBase运维基础——元数据逆向修复原理

背景 鉴于上次一篇文章——“云HBase小组成功抢救某公司自建HBase集群,挽救30+T数据”的读者反馈,对HBase的逆向工程比较感兴趣,并咨询如何使用相应工具进行运维等等。总的来说,就是想更深...

Mr_zebra ⋅ 05/02 ⋅ 0

八年磨一剑,阿里云ApsaraDB for HBase2.0正式上线

一)HBase2.0和阿里云的前世今生 ApsaraDB for HBase2.0于2018年6月6日即将正式发布上线啦! 它是基于社区HBase2.0稳定版的升级,也是阿里HBase多年的实践经验和技术积累的持续延伸,全面解决...

天斯 ⋅ 06/05 ⋅ 0

Accordion:HBase一种内存压缩算法

现如今,人们对基于HBase的产品的读写速度要求越来越高。在理想情况下,人们希望HBase 可以在保证其可靠的持久存储的前提下能并拥有内存数据读写的速度。为此,在HBase2.0中引入According算法...

HBase技术社区 ⋅ 05/01 ⋅ 0

八年磨一剑,解读阿里云ApsaraDB for HBase2.0

一.HBase2.0和阿里云的前世今生 ApsaraDB for HBase2.0于2018年6月6日即将正式发布上线啦! ApsaraDB for HBase2.0是基于社区HBase2.0稳定版的升级,也是阿里HBase多年的实践经验和技术积累的...

HBase技术社区 ⋅ 06/19 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Spring表达式语言(SpEL)

1、SpEL引用 Spring EL在bean创建时执行其中的表达式。此外,所有的Spring表达式都可以通过XML或注解的方式实现。下面将使用Spring表达式语言(SpEL),注入字符串,整数,Bean到属性。 SpEL的...

霍淇滨 ⋅ 30分钟前 ⋅ 0

Gradle使用阿里云镜像

gradle 生命周期中有一个初始化( Initialization )的过程,这个过程运行在 build script 之前,我们可以在这个地方做一点系统全局的设置,如配置仓库地址。 你可以在以下几个位置实现仓库地址...

明MikeWoo ⋅ 38分钟前 ⋅ 0

appium+python3.6

1.安装jdk1.8(不知道为啥只识别1.8,1.10不识别,所以为了少折腾,迁就安装1.8) http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 配置 JAVA_HOME:...

Kampfer ⋅ 57分钟前 ⋅ 0

详解Apache 日志分割教程

一、日志切割 安装cronolog CentOS 5.3中编译安装Apache日志默认是不切割的,需要用用工具Cronnolog进行日志切割。 1.下载及安装 wget http://cronolog.org/download/cronolog-1.6.2.tar.gz ...

dragon_tech ⋅ 59分钟前 ⋅ 0

Keepalived介绍

负载均衡器(Load Balancer, LB )是一组能够将IP数据流以负载均衡形式转发到多台物理服务器的集成软件。有硬件负载均衡器和软件负载均衡器之分,硬件负载均衡器主要是在访问网络和服务器之间...

寰宇01 ⋅ 59分钟前 ⋅ 0

java8-Collections and Streams

stream和集合的区别是什么? 1.在计算的时候处理不同, 2.every element should be computed in the memory and then to be part of collections stream Stream apis filter with a predica......

writeademo ⋅ 今天 ⋅ 0

Confluence 6 重新获得附件指南

每一个文件在恢复上传到 Confluence 的时候必须单独重命名,你可以通过下面说明的 3 个方法中选择一个进行操作: 选择 A - 通过文件名恢复附件 如果你知道你需要恢复的每一个文件名,尤其是你...

honeymose ⋅ 今天 ⋅ 0

【每天一个JQuery特效】根据状态确定是否滑入或滑出被选元素

主要效果: 本文主要采用slideToggle()方法实现以一行代码同时实现以展开或收缩的方式显示或隐藏被选元素。 主要代码如下: <!DOCTYPE html><html><head><meta charset="UTF-8">...

Rhymo-Wu ⋅ 今天 ⋅ 0

度量.net framework 迁移到.net core的工作量

把现有的.net framework程序迁移到.net core上,是一个非常复杂的工作,特别是一些API在两个平台上还不能同时支持。两个类库的差异性,通过人工很难识别全。好在微软的工程师们考虑到了我们顾...

李朝强 ⋅ 今天 ⋅ 0

请不要在“微服务”的狂热中迷失自我!

微服务在过去几年一直是一个非常热门的话题(附录1)。何为“微服务的疯狂”,举个例子: 众所周知,Netflix在DevOps上的表现非常棒。Netfix可以做微服务。因此:如果我做微服务,我也将非常...

harries ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部