Co2y's Blog

Hadoop异常处理

Hadoop家族使用过程中一些异常的处理记录,主要包括Hadoop(MR,YARN),HBase,Hive,Phoenix,CDH等。大部分异常都可以通过google搜到,为了避免重复搜索和确保解决方法可用,故作此记录。不断更新。

目录

MAPREDUCE-5831 Old MR client is not compatible with new MR application

1
2
Exception in thread "main" java.lang.IllegalArgumentException: No enum constant org.apache.hadoop.mapreduce.JobCounter.MB_MILLIS_MAPS
at java.lang.Enum.valueOf(Enum.java:236)

在使用importtsv的时候遇到这个问题,由于HBase impottsv导入数据的时候,需要启动底层MapReduce Job,Job运行在YARN集群上。但是HBase-0.98.7中使用的YARN、MR的版本都是2.2.0。在MR 2.3+后LIB库有一些变动,例如 JobCounter.MB_MILLIS_REDUCES就是在2.3版本加入的。而HBase-0.98使用的YARN/MR版本没有这个变量,所以会抛出“No enum constant”异常。

解决方法:升级HBase,HBase1.0之后的lib下是MR 2.3+,或者把Hadoop share里的jar包拷贝到HBase/lib下,需要注意的是除了MR和YARN的包之外还有HDFS和COMMON的,要拷贝全,不然会导致HBase无法启动。再或者使用HBase Java Client API进行导入,避免直接importtsv。

Hadoop集群机器名称要求

hadoop集群的hostname里面千万不要包括下划线,否则会报以下错误:

1
2
java.lang.IllegalArgumentException: Does not contain a vali
d host:port authority:

TEZ的一个BUG

按照官方教程部署之后,tez可以和mapreduce共同使用,并且如果是在hive的cli中用的话更方便,只要set hive.execution.engine = tez即可,但是这次报错了。

hive的cli中并没有太多信息,查看hive的日志/tmp/${USER}/hive.log也没有发现有用的信息,只是偶尔会出现retrying connect 10 times的错误,让我一直以为是通信的问题。

但是发现集群中的机器并没有开iptables,google也没有得到有用的结果,只有一个人在stackoverflow上提出了相同的问题,他也认为是tez和resourcemanager的通信问题,它的解决方法是换了一个tez版本。于是我编译了从0.52到0.80的所有tez发行版本都没有用。

之后继续看tez application master的日志发现是application master没有启动导致的通信失败,但是从中也没有看出是什么原因导致的application master启动失败,stacktrace中的异常信息也没什么用。官方的tez问题查找文档也没有给出其它的解决方案。

最后在从节点的nodemanager的日志信息中$HADOOPHOME/logs中发现是application master启动占用的virtual memory超出了限制,最坑的是这个oom的错误不是每次都报的。

之后google tez的oom异常,找到了一些解决方法,大多是设置yarn和hive-tez的jvm参数,最后通过修改yarn-site.xml 解决了问题

1
2
3
<name>yarn.nodemanager.vmem-check-enabled</name>
<value>false</value>
</property>

hbase region server exiting address already in use

  1. 先查看端口是否被占用,处理对应进程
  2. 可能是时间不同步,用ntp可以解决
  3. 如果并没有发现端口占用的情况,重启hbase集群可能可以解决
  4. zookeeper数据残留

phoenix udf

phoenix udf需要更换包名才能覆盖掉原来的类,这是因为除了hbase.dynamic.jars.dir在HDFS上外,本地默认是/tmp/hbase-{User}/local/jars里面还有之前的jar包,需要手动删除掉才行。

Limitations

  1. The jar containing the UDFs must be manually added/deleted to/from HDFS. Adding new SQL statements for add/remove jars(PHOENIX-1890)
  2. Dynamic class loader copy the udf jars to {hbase.local.dir}/jars at the phoenix client/region server when the udf used in queries. The jars must be deleted manually once a function deleted.
  3. functional indexes need to manually be rebuilt if the function implementation changes(PHOENIX-1907)
  4. once loaded, a jar will not be unloaded, so you’ll need to put modified implementations into a different jar to prevent having to bounce your cluster(PHOENIX-1907)
  5. to list the functions you need to query SYSTEM.“FUNCTION” table(PHOENIX-1921))

hive shell 启动时连接8020端口

hive会认为namenode在8020端口,也就是core-site.xml里fs.defaultFS的值默认的是8020端口,通常我们会改成9000端口,这时hive还是会连8020导致connection refused。 可以在hive-site.xml里再次填写如下配置

1
2
3
4
<property>
<name>fs.defaultFS</name>
<value>hdfs://localhost:9000</value>
</property>

tephra guava 版本

安装tephra,根据官网配置之后,发现启动时报异常,某个类找不到。
解决方法:guava版本不匹配造成某个类的缺失。在phoenix目录下建一个lib目录 然后把guava-13.0.1放进去 这是根据tephra日志里面的classpath的顺序来决定的。另外通过查看tephra-env.sh可以得知,

1
2
# Add any extra classes to the classpath
export EXTRA_CLASSPATH=/home/experiment/phoenix-4.7.0-HBase-0.98-bin/lib

phoenix 无法创建事务类型表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
0: jdbc:phoenix:slave206,slave207,slave208,sl> CREATE TABLE my_table (k BIGINT PRIMARY KEY, v VARCHAR) TRANSACTIONAL=true;
Error: ERROR 1078 (44A09): Cannot create a transactional table if transactions are disabled. tableName=MY_TABLE (state=44A09,code=1078)
java.sql.SQLException: ERROR 1078 (44A09): Cannot create a transactional table if transactions are disabled. tableName=MY_TABLE
at org.apache.phoenix.exception.SQLExceptionCode$Factory$1.newException(SQLExceptionCode.java:454)
at org.apache.phoenix.exception.SQLExceptionInfo.buildException(SQLExceptionInfo.java:145)
at org.apache.phoenix.schema.MetaDataClient.createTableInternal(MetaDataClient.java:1815)
at org.apache.phoenix.schema.MetaDataClient.createTable(MetaDataClient.java:922)
at org.apache.phoenix.compile.CreateTableCompiler$2.execute(CreateTableCompiler.java:194)
at org.apache.phoenix.jdbc.PhoenixStatement$2.call(PhoenixStatement.java:340)
at org.apache.phoenix.jdbc.PhoenixStatement$2.call(PhoenixStatement.java:328)
at org.apache.phoenix.call.CallRunner.run(CallRunner.java:53)
at org.apache.phoenix.jdbc.PhoenixStatement.executeMutation(PhoenixStatement.java:326)
at org.apache.phoenix.jdbc.PhoenixStatement.execute(PhoenixStatement.java:1388)
at sqlline.Commands.execute(Commands.java:822)
at sqlline.Commands.sql(Commands.java:732)
at sqlline.SqlLine.dispatch(SqlLine.java:807)
at sqlline.SqlLine.begin(SqlLine.java:681)
at sqlline.SqlLine.start(SqlLine.java:398)
at sqlline.SqlLine.main(SqlLine.java:292)

这里需要在客户端设置

1
2
3
4
<property>
<name>phoenix.transactions.enabled</name>
<value>true</value>
</property>

也就是在phoenix/lib/下的hbase-site.xml里设置

接上 《phoenix无法创建事务类型表中》

上面提到需要在客户端设置phoenix.transactions.enabled,这也是直接用jdbc读写事务表报NPE的原因。

phoenix 注意单双引号

小写的表名,字段名都要加双引号。 做hbase映射时也要加双引号,并且映射不是秒建的。

hadoop.tmp.dir

出现

1
Exception in thread "main" java.lang.IllegalArgumentException: Wrong FS: file:/home/hadoop/tmp/partitions_a5981b72-eaa7-4b05-93b4-dab30f681387, expected: hdfs://master:9000

这是我在用phoenix bulkload工具时遇到的错误,经过google发现不少同学也遇到了相同的错误,但是并没有找到解决方法。

经过排查发现是因为hadoop.tmp.dir配置到了本地,出现此错误的core-site.xml里该配置项的值一般都加了file:/。这样会强制把临时目录设置为本地,而其实这个目录是在HDFS上的。

修改此配置项,把前面的file:/去掉并在hdfs上找一个合适的目录即可解决此问题。

no datanode to stop

问题的原因是hadoop在stop的时候依据的是datanode上的mapred和dfs进程号。而默认的进程号保存在/tmp下,linux 默认会每隔一段时间(一般是一个月或者7天左右)去删除这个目录下的文件。因此删掉hadoop-hadoop-jobtracker.pid和hadoop-hadoop-namenode.pid两个文件后,namenode自然就找不到datanode上的这两个进程了。

在配置文件hadoop_env.sh中配置export HADOOP_PID_DIR可以解决这个问题。

1
kill $(jps | grep DataNode | awk '{print $1}')

hive 与 hbase 集成

在hive建立与hbase映射的表时,执行insert into / insert overwrite 时报错:

1
must specify tablename

经过google, hbase0.98+hive1.2.1不少同学遇到这个问题,需要在建表的时候多指定一个属性。