大数据平台常见异常处理汇总

本博客记录工作中遇到的,大数据相关各个组件的异常处理过程,养成良好的问题归纳总结习惯,累积问题解决经验与思路。

Spark相关

  1. Shuffle异常导致任务失败
    报错:org.apache.spark.shuffle.MetadataFetchFailedException: Missing an output location for shuffle 1
    原因:
    shuffle分为shuffle write和shuffle read两部分。
    shuffle write的分区数由上一阶段的RDD分区数控制,shuffle read的分区数则是由Spark提供的一些参数控制。
    shuffle write可以简单理解为类似于saveAsLocalDiskFile的操作,将计算的中间结果按某种规则临时放到各个executor所在的本地磁盘上。
    shuffle read的时候数据的分区数则是由spark提供的一些参数控制。可以想到的是,如果这个参数值设置的很小,同时shuffle read的量很大,那么将会导致一个task需要处理的数据非常大。结果导致JVM crash,从而导致取shuffle数据失败,同时executor也丢失了,看到Failed to connect to host的错误,也就是executor lost的意思。有时候即使不会导致JVM crash也会造成长时间的gc。
    解决思路:减少shuffle的数据量和增加处理shuffle数据的分区数
    ①spark.sql.shuffle.partitions控制分区数,默认为200,根据shuffle的量以及计算的复杂度提高这个值 shuffle并行度
    ②提高spark.executor.memory
    ③map side join或是broadcast join来规避shuffle的产生
    ④分析数据倾斜 解决数据倾斜
    ⑤增加失败的重试次数和重试的时间间隔
    通过spark.shuffle.io.maxRetries控制重试次数,默认是3,可适当增加,例如10。
    通过spark.shuffle.io.retryWait控制重试的时间间隔,默认是5s,可适当增加,例如10s。
    ⑥类似RemoteShuffleService的服务,解决Shuffle单台机器IO瓶颈,记录Shuffle状态,大批量提升Shuffle效率和稳定性。

  2. SparkSQL报awaitResult异常
    报错:org.apache.spark.SparkException: Exception thrown in awaitResult
    原因:广播数据超时
    解决:spark.sql.broadcastTimeout=1200 默认大小300

  3. HiveOnSpark不能创建SparkClient及Return Code 1异常
    报错:FAILED:SemanticException Failed to get a spark session: org.apache.hadoop.hive.ql.metadata.HiveException: Failed to create spark client.
    Error while processing statement: FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.spark.SparkTask
    原因:以上报错证明初始化Spark失败,而以前不会失败,所以大概率是资源问题而不是代码问题,查看Yarn队列发现所提交的队列已满且已超过能申请资源的上限(虚线部分),故任务启动失败
    解决:CM界面->群集->动态资源池配置->提高队列的资源权重(上限也会响应提高)->刷新动态资源池配置

  4. ExecutorLost、Task Lost
    报错:
    1.[executor lost] WARN TaskSetManager: Lost task 1.0 in stage 0.0 (TID 1, aa.local): ExecutorLostFailure (executor lost)
    2.[task lost] WARN TaskSetManager: Lost task 69.2 in stage 7.0 (TID 1145, 192.168.47.217): java.io.IOException: Connection from /xx.xxx.xx.xxx:xxxxx closed
    3.[timeout] java.util.concurrent.TimeoutException: Futures timed out after [120 second
    ERROR TransportChannelHandler: Connection to /xxx.xxx.xx.xxx:xxxxx has been quiet for 120000 ms while there are outstanding requests. Assuming connection is dead; please adjust spark.network.timeout if this is wrong
    原因:节点资源不足、网络延迟波动、GC导致Executor运行慢等原因
    解决:①spark.network.timeout的值(默认为120s,配置所有网络传输的延时),根据情况改成300(5min)或更高 ②分别增加各类超时参数
    spark.core.connection.ack.wait.timeout
    spark.akka.timeout
    spark.storage.blockManagerSlaveTimeoutMs
    spark.shuffle.io.connectionTimeout
    spark.rpc.askTimeout or spark.rpc.lookupTimeout

HDFS相关

  1. 数据块丢失且命令无法修复
    起因:多张表查询发现如下报错,提示块丢失
    alt
    分析:CM界面看HDFS丢失块,发现有2500多,大批量块丢失可能的原因:
        1.DataNode与NameNode未通信,DataNode进程未启动
        2.DataNode数据磁盘损坏,数据丢失
    3.一个文件的全部副本丢失
    解决过程:
    尝试修复丢失块:hdfs debug recoverLease -path  -retries 
    显示修复成功,但使用hadoop fs -text  还是报MissingBlock无法读取
    使用fsck检测坏块 hdfs fsck /user/hive/warehouse
    alt
    发现绝大多数block名称都带有172.xxx.xxx.11 定位到可能是172.xxx.xxx.11节点的DataNode可能存在问题
    通过CM日志和机器上进程状态判断172.xxx.xxx.11的DataNode已与NameNode保持心跳,运行正常,进而怀疑磁盘坏了(概率太小)
    查看CM配置和机器磁盘,发现少配置了些硬盘路径,原因是在配置新节点磁盘路径时误修改整个配置组的磁盘路径,导致该配置组中所有DataNode缺少磁盘,进而出现块丢失且无法修复的问题。
    解决:还原磁盘配置,滚动重启该配置组中的DataNode,将不同机器配置分成多个配置组,重新修改配置
    重启过程中丢失块数一直在减少:
    alt
    最终恢复正常
    总结:
    1.CM上修改配置一定要慎重,注意修改配置组中某台节点的配置会影响整个配置组中所有节点的配置
    2.CM显示DataNode重启成功只是进程启动成功,但日志出现“Total time to add all replicas to map”字眼才是真正完成启动
    3.https://hdfs-site/dfshealth.html#tab-overview 从HDFS WebUI获取更多信息(丢失块的信息一目了然)

  2. Win开发Hadoop环境winutils
    错误:Could not locate executable null\bin\winutils.exe in the Hadoop binaries
    解决:将winutils.exe放在HADOOP_HOME\bin下,然后代码里System.setProperty(“hadoop.home.dir”, “D:\Programming\Env\Hadoop\hadoop-2.7.2\“)或设置环境变量HADOOP_HOME和PATH后重启电脑
    winutils.exe下载地址:winutils-master

  3. Namenode is not formatted
    错误Namenode is not formatted
    分析:一般新部署的HDFS才会提示需要格式化(hadoop namenode -format),而生产环境Namenode一旦有异常,也可能出现这样的问题,但我不能格式化生产环境啊!
    NN日志如下:
    alt
    可知识由于加载fsimage异常,去NameNode的存储路径/dfs/nn/发现没有文件,而其他节点/dfs/nn目录下有current目录,current目录下有fsimage。所以可以判定该Namenode无法启动就是因为fsimage丢失
    解决:scp这个current目录,权限与之前的一致(一般为hdfs:hdfs权限)

  4. 修复HDFS坏块
    查看坏块可通过

    hdfs fsck /
    hadoop dfsadmin -report

    修复坏块除了上面讲过的hdfs debug recoverLease -path  -retries 命令外,还可以通过hadoop fs -setrep -R 3 / 命令,设置副本,副本小于3的情况会自动恢复三副本,修复后还有坏块那就是一个副本都没有了,只能丢了。

  5. 两个NN均为Standby,重启后过一会又都Standby
    NN均报错:
    java.util.concurrent.ExecutionException: java.io.IOException: Cannot find any valid remote NN to service request!
    Caused by: java.io.IOException: Cannot find any valid remote NN to service request!
    Exception from remote name node RemoteNameNodeInfo [nnId=namenode37, ipcAddress=xxxx, httpAddress=xxxx], try next.
    org.apache.hadoop.ipc.RemoteException(org.apache.hadoop.ipc.StandbyException): Operation category JOURNAL is not supported in state standby. Visit https://s.apache.org/sbnn-error
    解决:强制切换主备sudo -uhdfs hdfs haadmin -transitionToActive –forcemanual namenode37(nnId在hdfs-site有配) 切换后重启Failover Controller或ZKFC。

  6. 基于Sentry认证的HDFS集群NN启动异常
    NN进程启动成功但是一直处于忙碌状态,查看NN的日志

    晚上9点53:24.664分 INFO SentryAuthorizationInfo Refresh interval [500]ms, retry wait [30000]
    晚上9点53:24.664分 INFO SentryAuthorizationInfo stale threshold [60000]ms
    晚上9点53:24.669分 INFO HMSPaths HMSPaths:[/user/hive/warehouse, /user/hive/xxxx] Initialized
    晚上9点53:24.681分 INFO SentryTransportPool Creating pool for xxx:8038,xxx:8038 with default port 8038
    晚上9点53:24.683分 INFO SentryTransportPool Adding endpoint xxx:8038
    晚上9点53:24.683分 INFO SentryTransportPool Adding endpoint xxx:8038
    晚上9点53:24.683分 INFO SentryTransportPool Connection pooling is disabled
    日志卡在这不继续了,卡在这

    与此同时两个SentryServer有一台发生OOM,不稳定
    原因:由于基于Sentry认证,HDFS的NN在启动时,Sentry会全量收集HMSPaths下的ACL信息,会驻留在Sentry内存中,如果Sentry内存不足容易OOM,需要通过增加堆内存的方式解决。两个SentryServer虽然可以负载均衡高可用,当一个SentryServer宕掉请求才会转移到另一个节点,而OOM时,请求会一直卡住,不会自动转移,导致NN启动异常。
    解决:增加Sentry堆内存,不盲目加,根据当前Hive服务器数、库数、表数、分区数、列数及视图数进行评估,具体评估标准如下:
    alt
    如图推算:每百万个Hive对象(库、表、分区数)需要配置2.25G的Sentry最大堆内存

Hive相关

  1. HiveMetaStore状态不良导DDLSQL耗时200s以上
    HMS进程报错:hive metastore server Failed to sync requested HMS notifications up to the event ID xxx
    原因分析:查看sentry异常CounterWait源码发现传递的id比currentid大导致一直等待超时,超时时间默认为200s(sentry.notification.sync.timeout.ms)。
    开启了hdfs-sentry acl同步后,hdfs,sentry,HMS三者间权限同步的消息处理。当突然大批量的目录权限消息需要处理,后台线程处理不过来,消息积压滞后就会出现这个异常。这个异常不影响集群使用,只是会导致create,drop table慢需要等200s,这样等待也是为了追上最新的id。我们这次同时出现了HMS参与同步消息处理的线程被异常退出,导致sentry的sentry_hms_notification_id表数据一直没更新,需要重启HMS。如果积压了太多消息,让它慢慢消费处理需要的时间太长,可能一直追不上,这时可以选择丢掉这些消息。
    解决:
    ①可以通过设置sentry.notification.sync.timeout.ms参数调小超时时间,减小等待时间,积压不多的话可以让它自行消费处理掉。
    ②丢掉未处理的消息,在sentry的sentry_hms_notification_id表中插入一条最大值(等于当前消息的id,从notification_sequence表中获取) ,重启sentry服务。(notification_log 表存储了消息日志信息)

Yarn相关

  1. 应用提交报Retrying connect to server 0.0.0.0
    原因:应用没有认到yarn-site.xml或者yarn-site.xml配置不正确
    解决:①指定HADOOP_CONF_DIR ②确认yarn-site.xml

    <property>
      <name>yarn.resourcemanager.address</name>
      <value>master:8032</value>
    </property>
    <property>
      <name>yarn.resourcemanager.scheduler.address</name>
      <value>master:8030</value>
    </property>
    <property>
      <name>yarn.resourcemanager.resource-tracker.address</name>
      <value>master:8031</value>
    </property>
  2. 内存不足Container退出
    报错:Diagnostics: Container [pid=91869,containerID=container_e23_1574819880505_43157_01_000001] is running beyond physical memory limits. Current usage: 9.0 GB of 9 GB physical memory used; 12.8 GB of 18.9 GB virtual memory used. Killing container.Dump of the process-tree for container_e23_1574819880505_43157_01_000001
    分析:”physical memory used”为物理内存占用(应用已占满9G),”virtual memory used”为虚拟内存占用,18.9GB是取决于yarn.nodemanager.vmem-pmem-ratio(yarn-site.xml中设置的虚拟内存和物理内存比例,默认2.1),报错是因为物理内存不足,是任务设置的内存少了
    解决思路:
    ①如果资源充足,增加任务并行度分担任务负载
    ②增大任务可用资源(注意不要超过单台NM可分配上限yarn.scheduler.maximum-allocation-mb的值)
    ③适当增大yarn.nodemanager.vmem-pmem-ratio,适当调高虚拟内存比例
    ④[不建议]取消内存的检查:在yarn-site.xml或者程序中中设置yarn.nodemanager.vmem-check-enabled为false

Hive相关

  1. HBase外部表报Unexpected end-of-input
    起因:使用Hive创建HBase外部表时正常,但使用HBase外部表时报Unexpected end-of-input: was expecting closing
    分析过程:翻阅源码部分发现异常是在解析外部表创建JSON时发生,于是对比建表语句和Hive元数据库中的TABLE_PARAMS表信息得到原因
    原因:创建hbase外部表catalog太长导致schema太长,而hive元数据表mysql里的table_params字段param_value字段类型是varchar(4000)建表时由于schema太长,超过4000字符的部分被截断。而使用该表的时候会读元数据,但因为元数据不完整而报错。
    解决:
    ①分多次建表
    ②改varchar(4000)为longtext然后重建表(影响无法评估,没尝试)

  2. Hive和Spark查询Hive表报java.net.UnknownHostException: nameservice1
    分析:由于机器HDFS HA配置发生变动,关掉了高可用,所以nameservice变成了ip:8020,报这个错,首先检查了/etc/hadoop/conf/hdfs-site.xml里面无dfs.nameservices配置,证明配置文件没问题。使用hivecli,desc formatted某几张表,发现表的LOCATION均为hdfs://nameservice1/xx 找到了问题的原因,元数据错误,所以需要去Hive元数据库批量修改元数据。
    解决:连接到Hive metastore元数据库,批量修改LOCATION:
    update hive.SDS set LOCATION=concat(“hdfs://ip:8020”,substring(LOCATION,20,length(LOCATION)-19)) where LOCATION like “hdfs://nameservice1%”;
    update hive.DBS set DB_LOCATION_URI=concat(“hdfs://ip:8020”,substring(DB_LOCATION_URI,20,length(DB_LOCATION_URI)-19)) where DB_LOCATION_URI like “hdfs://nameservice1%”;
    无需重启服务即可生效,问题解决。

HBase相关

  1. 集群新增RS致另一RS异常退出
    alt
    上线的RegionServer会触发Region移动,报错前有Flush操作,因为Region移动前会先Flush Region
    异常相关源码:
    alt
    Flush Memstore到HFile这个过程未发生异常,但Flush一个Memstore后跟踪Memstore总大小未发生变化,即内存清理失败 超过5次就中止这个RS
    分析:版本BUG

  2. Couldn’t read snapshot info from hdfs:xx/hbase/.hbase-snapshot/xxx导致Master不可用
    hbase shell执行list命令报ERROR: org.apache.hadoop.hbase.PleaseHoldException: Master is initializing
    跟进Master日志看到Couldn’t read snapshot info from hdfs:xx/hbase/.hbase-snapshot/xxx,Master状态不可用
    分析:由于HDFS的原因导致HBase的Snapshot文件丢失,详细看了一下,其他snapshot目录下有.snapshot以及data.manifest,而这个没有
    操作:删除这个snapshot目录 重启HMaster
    修复后scan操作又报Unknown table xxx,而且几乎所有表都不能scan
    操作:首先想到的就是修复HBase元数据hbase hbck -fixMeta
    修复后继续scan,报错ERROR: No server address listed in hbase:meta for region t1,,1536659773616.09db0b8b3b7f8cd81dde86c9f1e41306. containing row rowkey001: 1 time…
    分析:查询hbase:meta表scan ‘hbase:meta’,{LIMIT=>10,FILTER=>”PrefixFilter(‘test_ray’)”}
    alt
    发现表元数据中都没有regionserver的信息,正常情况是这样的:
    alt
    解决:重新对region分区:hbase hbck -fixAssignments 最终服务和数据均恢复正常

Kafka相关

  1. ConsumerRebalanceFailedException异常解决
    报错:kafka.common.ConsumerRebalanceFailedException: group_xxx-1446432618163-2746a209 can’t rebalance after 5 retries
    分析:官网给出了异常的相关说明和解决方案
    consumer rebalancing fails (you will see ConsumerRebalanceFailedException): This is due to conflicts when two consumers are trying to own the same topic partition. The log will show you what caused the conflict (search for “conflict in “).
    If your consumer subscribes to many topics and your ZK server is busy, this could be caused by consumers not having enough time to see a consistent view of all consumers in the same group. If this is the case, try Increasing rebalance.max.retries and rebalance.backoff.ms.
    Another reason could be that one of the consumers is hard killed. Other consumers during rebalancing won’t realize that consumer is gone after zookeeper.session.timeout.ms time. In the case, make sure that rebalance.max.retries * rebalance.backoff.ms > zookeeper.session.timeout.ms.
    简单来说就是同一个topic的同一个分区被多个消费者消费,发生冲突
    解决:
    ①增加相关topic的partition数
    ②提高kafka的consumer如下两项配置
    rebalance.backoff.ms=2000
    rebalance.max.retries=10

其他

  1. Zookeeper日志和快照过大
    解决1:cd $ZOOKEEPER_HOME;bin/zkCleanup.sh {dataDir} 5;bin/zkCleanup.sh {snapshotDir} 5 并设置成定时调度
    解决2:从3.4.0开始,zookeeper提供了自动清理snapshot和事务日志的功能,通过配置autopurge.snapRetainCount和autopurge.purgeInterval这两个参数能够实现定时清理了。这两个参数都是在zoo.cfg中配置的:
    autopurge.purgeInterval 这个参数指定了清理频率,单位是小时,需要填写一个1或更大的整数,默认是0,表示不开启自己清理功能。
    autopurge.snapRetainCount 这个参数和上面的参数搭配使用,这个参数指定了需要保留的文件数目。默认是保留3个。
    原理:Zookeeper不会删除旧的快照和日志文件,zkCleanup.sh可以帮助合理清理当前节点的旧的日志和快照文件解决磁盘空间。其中dataDir是特定服务集合的znode存储的永久副本,对znode的所有更改会附加到log日志中,snapshotDir是永久快照。zkCleanup.sh将保留最后一个快照和相关的log日志,清除其他的快照和日志。注意最后一个参数值要大于等于3,日志损坏的情况下保证有3个以上备份。
    参考:zookeeperAdmin.html#sc_maintenance

你自以为的极限,只是别人的起点