我已经和distcp一起玩了好几天了,我发誓我已经足够google了。这是我的用例:
我在某个位置有一个主文件夹,说 / hdfs / root ,有很多子目录(深度不固定)和文件。
卷:200,000个文件〜= 30个GO
我需要在另一个位置复制客户端 / hdfs / root 的子集,例如/ hdfs / dest 该子集由可以随时间更新的绝对路径列表定义。
卷:50,000个文件〜= 5个GO
您理解我不能使用简单的hdfs dfs -cp /hdfs/root /hdfs dest
,因为它没有经过优化,它会占用每个文件,并且它没有更新模式。
我最终以两种方式使用hadoop distcp:
Algo 1 (simplified):
# I start up to N distcp jobs in parallel for each subdir, with N=MAX_PROC (~30)
foreach subdir in mylist:
# mylist = /hdfs/root/dirX/file1 /hdfs/root/dirX/file2 ...
mylist = buildList(subdirs)
hadoop distcp -i -pct -update mylist /hdfs/dest/subdir &
和
Algo 2
# I start one distcp that has a blacklist
blacklist = buildBlackList()
hadoop distcp -numListstatusThread 10 -filters blacklist -pct -update /hdfs/root /hdfs/dest
Algo 2甚至没有启动,似乎在源和黑名单之间建立差异对他来说太难了,所以我使用Algo 1,它可以工作。
知道我需要在Oozie工作流程中安排所有工作流程。 我把algo 2放在shell动作中,因为我有很多distcp命令而且我没有掌握递归或在oozie中循环。
一旦启动,过了一会儿,我收到以下错误: 容器超出物理内存限制。当前用法:使用17.2 GB的16 GB物理内存
好吧那么,我会增加更多的记忆:
<configuration>
<property>
<name>oozie.launcher.mapreduce.map.memory.mb</name>
<value>32768</value>
</property>
<property>
<name>oozie.launcher.mapreduce.map.java.opts</name>
<value>-Xmx512m</value>
</property>
</configuration>
我仍然得到:容器超出物理内存限制。当前用法:使用32 GB GB 32 GB物理内存但是这项工作的寿命是前一次的两倍。
我的群集上的RAM不是无限的,所以我无法继续前进。以下是我的假设:
此外,我对内存管理还有很多不了解的事情,它非常模糊(yarn,oozie,jvm,mapreduce)。
谷歌搜索时,我注意到很少有人在讨论真正的distcp用例,这篇文章是4天之久:https://community.hortonworks.com/articles/71775/managing-hadoop-dr-with-distcp-and-snapshots.html并解释了快照用法,我不能在我的案例中使用。
我也听说过http://atlas.incubator.apache.org最终通过“标记”文件并授予特定用户访问权限来解决我的问题,因此我们可以避免复制到某个位置。我的管理团队正在研究它,但我们不会让它知道生产。
我非常绝望。帮助我。
答案 0 :(得分:7)
YARN容器建立在Linux&#34; cgroups&#34;之上。这些&#34; cgroups&#34;用于对CPU进行软限制,但不对RAM进行限制...
因此,YARN使用了一种笨拙的解决方法:它会定期检查每个容器使用多少RAM,并且强制杀死任何超过配额的内容。所以你丢失了执行日志,只得到你看到的那个可怕的消息。
在大多数情况下,您正在运行某种JVM二进制文件(即Java / Scala实用程序或自定义程序),因此您可以通过设置自己的JVM配额(尤其是-Xmx
)来逃避,以便始终保持在YARN限制下。这意味着由于安全边际,一些浪费的RAM。但最糟糕的情况是,当JVM内存不足时,JVM会彻底失败,您可以获得执行日志 in extenso 并可以开始调整配额 - 或修复内存泄漏{ {1}}
那么在你的具体情况下会发生什么?您正在使用Oozie来启动shell - 然后shell启动:-/
命令,该命令在JVM中运行。嵌入式JVM 的必须设置最大堆大小。
hadoop
),那么你必须确保shell中的Java命令不会消耗超过28GB的堆(继续使用)安全的一面)。
如果幸运的话,设置一个env变量就可以了:
oozie.launcher.mapreduce.map.memory.mb
如果你不幸运,你将不得不打开export HADOOP_OPTS=-Xmx28G
hadoop distcp ...........
混合使用不同设置的不同env变量的整个混乱(由显然讨厌你的人设置,在你甚至不知道的初始脚本中)由JVM使用复杂的优先级规则进行解释。玩得开心。您可以查看that very old post有关挖掘位置的提示。