// open src file
in = srcstat.getPath().getFileSystem(job).open(srcstat.getPath());
reporter.incrCounter(Counter.BYTESEXPECTED, srcstat.getLen());
// open tmp file
out = create(tmpfile, reporter, srcstat);
// copy file
for(int cbread; (cbread = in.read(buffer)) >= 0; ) {
out.write(buffer, 0, cbread);
cbcopied += cbread;
reporter.setStatus(
String.format("%.2f ", cbcopied*100.0/srcstat.getLen())
+ absdst + " [ " +
StringUtils.humanReadableInt(cbcopied) + " / " +
StringUtils.humanReadableInt(srcstat.getLen()) + " ]");
}
} finally {
checkAndClose(in);
checkAndClose(out);
}
Mapper执行完之后,DistCp工具的服务端执行过程就全部完成了,回到客户端还会做一些扫尾的工作,例如同步Owner权限。这里会有一些问题,稍后我们一并分析。
问题分析
DistCp存在三大问题,下面来一一剖析:
1. 任务失败,map task报“DFS Read: java.io.IOException: Could not obtain block”
这是由于“_distcp_src_files”这个文件的备份数是系统默认值,例如hadoop-site.xml里面设置了dfs.replication=3,那么_distcp_src_files文件的备份数则创建之后就为3了。当map数非常多,以至于超过了_distcp_src_files文件三个副本所在datanode最大容纳上限的时候,部分map task就会出现获取不了block的问题。对于DistCp来说“-i”参数一般是绝对不能使用的,因为设置了该参数,这个问题就会被掩盖,带来的后果就是拷贝完缺失了部分数据。比较好的做法是在计算了总map数之后,自动增加_distcp_src_files这个文件的备份数,这样一来访问容纳上限也会跟着提高,上述问题就不会再出现了。当前社区已对此有了简单fix,直接将备份数设置成了一个较高的数值。一般说来对于计算资源有限的集群来说,过多的maptask并不会提高拷贝的效率,因此我们可以通过-m参数来设定合理的map数量。一般说来通过观察ganglia,bytes_in、bytes_out达到上限就可以了。
原文转自:http://www.taobaotest.com/blogs/2516