最近在部署Hive上线,结果在线上线下同时出现了MoveTask报错的现象,虽然两者错误的日志以及错误信息一样,但是经过分析解决又发现两者的原因是不一样的。

首先线下的错误日志:

2015-05-18 18:53:09,679 ERROR [main]: exec.Task (SessionState.java:printError(833)) - Failed with exception Unable to rename: hdfs://hadoop-master:9000/tmp/hive/hadoop/4d905c9f-ee65-4b1f-be96-93115b3aad61/hive_2015-05-18_18-51-42_401_2711668916550397051-1/-ext-10000 to: /user/hive/partitions/users_statis/dt_user_statis_behavior/event=play/period=0
org.apache.hadoop.hive.ql.metadata.HiveException: Unable to rename: hdfs://hadoop-master:9000/tmp/hive/hadoop/4d905c9f-ee65-4b1f-be96-93115b3aad61/hive_2015-05-18_18-51-42_401_2711668916550397051-1/-ext-10000 to: /user/hive/partitions/users_statis/dt_user_statis_behavior/event=play/period=0
at org.apache.hadoop.hive.ql.exec.MoveTask.moveFile(MoveTask.java:111)
at org.apache.hadoop.hive.ql.exec.MoveTask.execute(MoveTask.java:213)
at org.apache.hadoop.hive.ql.exec.Task.executeTask(Task.java:160)
at org.apache.hadoop.hive.ql.exec.TaskRunner.runSequential(TaskRunner.java:85)
at org.apache.hadoop.hive.ql.Driver.launchTask(Driver.java:1604)
at org.apache.hadoop.hive.ql.Driver.execute(Driver.java:1364)
at org.apache.hadoop.hive.ql.Driver.runInternal(Driver.java:1177)
at org.apache.hadoop.hive.ql.Driver.run(Driver.java:1004)
at org.apache.hadoop.hive.ql.Driver.run(Driver.java:994)
at org.apache.hadoop.hive.cli.CliDriver.processLocalCmd(CliDriver.java:247)
at org.apache.hadoop.hive.cli.CliDriver.processCmd(CliDriver.java:199)
at org.apache.hadoop.hive.cli.CliDriver.processLine(CliDriver.java:410)
at org.apache.hadoop.hive.cli.CliDriver.executeDriver(CliDriver.java:783)
at org.apache.hadoop.hive.cli.CliDriver.run(CliDriver.java:677)
at org.apache.hadoop.hive.cli.CliDriver.main(CliDriver.java:616)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.hadoop.util.RunJar.run(RunJar.java:221)
at org.apache.hadoop.util.RunJar.main(RunJar.java:136)

这个问题在http://blog.csdn.net/lucien_zong/article/details/10198533中有详细的描述

执行SQL时,最后一个任务是MoveTask,它的作用是将运行SQL生成的Mapeduce任务结果文件放到SQL中指定的存储查询结果的路径中,具体方法就是重命名
下面是 org.apache.hadoop.hive.ql.exec.MoveTask 中对结果文件重命名的一段代码:

//这个sourcePath参数就是存放Mapeduce结果文件的目录,所以它的值可能是
//hdfs://indigo:8020/tmp/hive-root/hive_2013-08-22_18-42-03_218_2856924886757165243/-ext-10000
if (fs.exists(sourcePath)) {
Path deletePath = null;
// If it multiple level of folder are there fs.rename is failing so first
// create the targetpath.getParent() if it not exist
if (HiveConf.getBoolVar(conf, HiveConf.ConfVars.HIVE_INSERT_INTO_MULTILEVEL_DIRS)) {
deletePath = createTargetPath(targetPath, fs);
}
//这里targetPath的值就是指定的放置结果文件的目录,值可能是 result/userName154122639/4e574b5d9f894a70b074ccd3981ca0f1
if (!fs.rename(sourcePath, targetPath)) {//上面产生的异常就是因为这里rename失败,进了if,throw了个异常
try {
if (deletePath != null) {
fs.delete(deletePath, true);
}
} catch (IOException e) {
LOG.info("Unable to delete the path created for facilitating rename"
+ deletePath);
}
throw new HiveException("Unable to rename: " + sourcePath
+ " to: " + targetPath);
}
}

rename的targetPath必须存在。

其实之前已经检查和创建targetPath了:

private Path createTargetPath(Path targetPath, FileSystem fs) throws IOException {
Path deletePath = null;
Path mkDirPath = targetPath.getParent();
if (mkDirPath != null & !fs.exists(mkDirPath)) {
Path actualPath = mkDirPath;
while (actualPath != null && !fs.exists(actualPath)) {
deletePath = actualPath;
actualPath = actualPath.getParent();
} <property> <name>hive.insert.into.multilevel.dirs</name> <value>true</value> </property> 
fs.mkdirs(mkDirPath);
}
return deletePath;//返回新创建的最顶层的目录,万一失败用来删除用
}

Apache出现过这个问题,已经解决掉了
CDH 竟然加了个参数 hive.insert.into.multilevel.dirs,默认是false,意思是我还有这BUG呢哈。
当你被坑了,想打个patch时,会发现改个配置就可以了。
意思是我保留这个BUG,但你要是被坑了也不能说我有BUG,自己改配置好了.
目前还没发现其他地方用到了这个参数,在这里唯一作用就是限制SQL中指定存放结果文件不存在的目录的深度不能大于1.
不过也没发现这有什么好处。

折腾半天,加个配置就可以了:

<property> <name>hive.insert.into.multilevel.dirs</name> <value>true</value> </property>

解决完线下的问题满心欢喜的以为可以解决线上的问题,结果发现了不行,仔细查看日志发现原来是因为缺包造成的

2015-05-18 19:22:03,799 ERROR [main]: exec.Task (SessionState.java:printError(861)) - Failed with exception Unable to move source hdfs://hadoop1:9000/tmp/hive/statistics/dt_statistics_content_daily/.hive-staging_hive_2015-05-18_19-11-45_323_132664610162390564-1/-ext-10000 to destination /tmp/hive/statistics/dt_statistics_content_daily
org.apache.hadoop.hive.ql.metadata.HiveException: Unable to move source hdfs://hadoop1:9000/tmp/hive/statistics/dt_statistics_content_daily/.hive-staging_hive_2015-05-18_19-11-45_323_132664610162390564-1/-ext-10000 to destination /tmp/hive/statistics/dt_statistics_content_daily
at org.apache.hadoop.hive.ql.metadata.Hive.moveFile(Hive.java:2483)
at org.apache.hadoop.hive.ql.exec.MoveTask.moveFile(MoveTask.java:105)
at org.apache.hadoop.hive.ql.exec.MoveTask.execute(MoveTask.java:222)
at org.apache.hadoop.hive.ql.exec.Task.executeTask(Task.java:160)
at org.apache.hadoop.hive.ql.exec.TaskRunner.runSequential(TaskRunner.java:88)
at org.apache.hadoop.hive.ql.Driver.launchTask(Driver.java:1638)
at org.apache.hadoop.hive.ql.Driver.execute(Driver.java:1397)
at org.apache.hadoop.hive.ql.Driver.runInternal(Driver.java:1183)
at org.apache.hadoop.hive.ql.Driver.run(Driver.java:1049)
at org.apache.hadoop.hive.ql.Driver.run(Driver.java:1039)
at org.apache.hadoop.hive.cli.CliDriver.processLocalCmd(CliDriver.java:207)
at org.apache.hadoop.hive.cli.CliDriver.processCmd(CliDriver.java:159)
at org.apache.hadoop.hive.cli.CliDriver.processLine(CliDriver.java:370)
at org.apache.hadoop.hive.cli.CliDriver.executeDriver(CliDriver.java:754)
at org.apache.hadoop.hive.cli.CliDriver.run(CliDriver.java:675)
at org.apache.hadoop.hive.cli.CliDriver.main(CliDriver.java:615)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.hadoop.util.RunJar.run(RunJar.java:221)
at org.apache.hadoop.util.RunJar.main(RunJar.java:136)
Caused by: java.io.IOException: Cannot find DistCp class package: org.apache.hadoop.tools.DistCp
at org.apache.hadoop.hive.shims.Hadoop23Shims.runDistCp(Hadoop23Shims.java:1123)
at org.apache.hadoop.hive.common.FileUtils.copy(FileUtils.java:553)
at org.apache.hadoop.hive.ql.metadata.Hive.moveFile(Hive.java:2461)
... 21 more

查看源码发现在调用moveFile时候会去调用Hadoop的distcp接口

@Override
public boolean runDistCp(Path src, Path dst, Configuration conf) throws IOException {
int rc; // Creates the command-line parameters for distcp
String[] params = {"-update", "-skipcrccheck", src.toString(), dst.toString()}; try {
Class clazzDistCp = Class.forName("org.apache.hadoop.tools.DistCp");
Constructor c = clazzDistCp.getConstructor();
c.setAccessible(true);
Tool distcp = (Tool)c.newInstance();
distcp.setConf(conf);
rc = distcp.run(params);
} catch (ClassNotFoundException e) {
throw new IOException("Cannot find DistCp class package: " + e.getMessage());
} catch (NoSuchMethodException e) {
throw new IOException("Cannot get DistCp constructor: " + e.getMessage());
} catch (Exception e) {
throw new IOException("Cannot execute DistCp process: " + e, e);
} return (0 == rc);
}

使用命令发现Hive环境变量中并没有Hadoop-Distcp-2.6.0.jar

hive -e 'set' | grep distcp

于是只要把hadoop/share/tools/下的Hadoop-Distcp-2.6.0.jar加载下来就行。

需要说明的是线上的Hive是1.1.0版本,线下的hive是0.14版本。同时需要注意的是线下的move文件的方式是rename,线上则用distcp方式,这跟Hive的版本有关了。

Hive的MoveTask错误的更多相关文章

  1. HIVE-执行distribute by时报错的解决过程---之如何分析hive执行的错误并解决

    在执行一条HIVE语句的时候报了以下错误,重新检查了所有步骤,重启所有服务,发现没有问题. 但发现一个有趣的事情 1,select sno,sname,sex,sage,sdept from stud ...

  2. hive on tez 错误记录

    1.执行过程失败,报 Container killed on request. Exit code is 143 如下图: 分析:造成这种原因是由于总内存不多,而容器在jvm中占比过高,修改tez-s ...

  3. hive安装启动错误总结

    错误一: Exception in thread "main" java.lang.NoClassDefFoundError: jline/console/completer/Ar ...

  4. hive安装配置错误

    1.Access denied for user 'hive'@'localhost' (using password: YES) 解决办法: 执行 hive --service metastore ...

  5. HADOOP在处理HIVE时权限错误的解决办法

    今天,小乔操作时发现问题: org.apache.hadoop.security.AccessControlException: Permission denied: user=root, acces ...

  6. hive类型转化错误,会错误提示指定分区参数

    select * from TRAD_LIST t WHERE t.dt >= '2017-10-18' and t.dt <= '2017-11-01' and t.con_level ...

  7. hive安装常见错误

    hive编译出错 mvn clean package -DskipTests -Phadoop-2 -Pdist 失败日志1 Failed to execute goal on project hiv ...

  8. hive启动一些错误记录

    java.lang.RuntimeException: Unable to instantiate org.apache.hadoop.hive.ql.metadata.SessionHiveMeta ...

  9. 在hive中遇到的错误

    1:如果在将文件导入到hive表时,查询结果为null(下图) 这个是因为在创建表的时候没有指定列分隔符,hive的默认分隔符是ctrl+a(/u0001)   2.当我复制好几行sql到hive命令 ...

随机推荐

  1. docker rancher 负载均衡做路由跳转

    介绍 我们要实现的目的是 根据负载均衡 跳转到指定的应用容器中 负载均衡中配置好 跳转的地址 当执行URL 请求的时候会自动跳转 测试方法 curl -v --header 'Host:mu.03in ...

  2. socket编程原理

    socket编程原理 1.问题的引入 1) 普通的I/O操作过程: UNIX系统的I/O命令集,是从Maltics和早期系统中的命令演变出来的,其模式为打开一读/写一关闭(open-write-rea ...

  3. java final keyword

    依据上下文环境,java的keywordfinal也存在着细微的差别,但通常指的是“这是无法改变的.”不想改变的理由由两种:一种是效率,还有一种是设计.因为两个原因相差非常远,所以关键子final可能 ...

  4. 【Android】isEmpty()

    对字符串进行非空判断,可以一次性进行两种空值的判断.当传入的字符串等于null或者等于空字符串的时候这个方法都会返回true,从而不需要单独去判断这两种空值,再利用逻辑运算符连接起来.

  5. skynet网络库socket-server

    最近在读大神云风的开源服务器架构skynet,其中的网络库,云风已经单独开来,可以独立使用. 开源地址: https://github.com/cloudwu/socket-server 网络库已经封 ...

  6. SQL语句对应的LINQ和Lambda语句

    1. 查询Student表中的所有记录的Sname.Ssex和Class列.select sname,ssex,class from studentLinq:    from s in Student ...

  7. 一个jquery的图片下拉列表 ddSlick

    [ddSlick]http://designwithpc.com/Plugins/ddSlick How to use with JSON data Include the plugin javasc ...

  8. /etc目录深入理解

    /etc This is the nerve center of your system, it contains all system related configuration files in ...

  9. ios7--系统自带的向右滑动手势返回上一个界面

    当从控制器A push到控制器B,我们返回控制器A,除了使用按钮返回 [self.navigationController pushViewController:Vc animated:YES]; 还 ...

  10. java中的包装类

    每一个包装类都对应一种基本数据类型.包装类有:Integer.character.Byte.Short.Long.Floot.Double.Boolean这八种,分别对应的基本数据类型是:int.ch ...