3

私は数日間 distcp と格闘してきました。これが私のユースケースです:

使用事例

/hdfs/rootなどの特定の場所にメインフォルダーがあり、多くのサブディレクトリ(深さは固定されていません)とファイルがあります。

ボリューム: 200,000 ファイル ~= 30 GO

クライアントのサブセット ( /hdfs/rootなど) のみを別の場所 (たとえば /hdfs/dest) にコピーする必要があります。このサブセットは、時間の経過とともに更新できる絶対パスのリストによって定義されます。

ボリューム: 50,000 ファイル ~= 5 GO

hdfs dfs -cp /hdfs/root /hdfs destシンプルは最適化されておらず、すべてのファイルが必要であり、更新モードがないため、使用できないことを理解しています。

ソリューション POC

最終的に、次の 2 つの方法で 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 ワークフロー

Oozie ワークフローですべてのワークフローをスケジュールする必要があることを知っています。私はdistcpコマンドをたくさん持っていて、oozieで再帰やループをマスターしていないので、アルゴ2をシェルアクションに入れました。

開始してしばらくすると、次のエラーが表示されます: コンテナーが物理メモリの制限を超えて実行されています。現在の使用量: 16 GB の物理メモリのうち 17.2 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 の物理メモリのうち 32.8 GB が使用されていますが、ジョブは前のジョブの 2 倍長く存続しました。

クラスターの RAM は無限ではないため、これ以上先に進むことはできません。ここに私の仮説があります:

  1. distcp ジョブがメモリを解放しない (JVM ガベージ コレクタ ?)
  2. Oozie は、すべての distcp ジョブの追加を現在のメモリ使用量として認識します。これはばかげています。
  3. これはこれを行う正しい方法ではありません(よく知っていますが、それでも)

また、メモリ管理について理解していないことがたくさんあります。かなり曖昧です (yarn、oozie、jvm、mapreduce)。

グーグルで調べていると、実際の distcp の使用例について話している人がほとんどいないことに気付きました。この投稿は 4 日前のものです。 htmlを参照し、私の場合は使用できないスナップショットの使用法について説明します。

http://atlas.incubator.apache.orgについても聞いたことがあります。これは、ファイルを「タグ付け」し、特定のユーザーにアクセスを許可することで最終的に問題を解決するため、特定の場所へのコピーを回避できます。私の管理チームはそれに取り組んでいますが、本番環境には反映されません。

私はかなり絶望的です。助けて。

4

1 に答える 1

8

YARN コンテナーは、Linux の「cgroup」の上に構築されます。これらの「cgroups」は、RAM ではなく CPU にソフト リミットを設定するために使用されます。
したがって、YARN は不器用な回避策を使用します。各コンテナーが使用する RAM の量を定期的にチェックし、クォータを超えたものを残忍に強制終了します。そのため、実行ログが失われ、見た恐ろしいメッセージだけが表示されます。

ほとんどの場合、ある種の JVM バイナリ (つまり、Java/Scala ユーティリティまたはカスタム プログラム) を実行しているため、独自の JVM クォータ (特に-Xmx) を設定して、常に YARN 制限を超えないようにすることができます。これは、安全マージンのために RAM がいくらか無駄になったことを意味します。しかし、最悪のケースは、JVM のメモリが不足しているときに JVM が完全に失敗することです。extensoで実行ログを取得し、クォータの調整を開始したり、メモリ リークを修正したりできます。:-/

では、あなたの特定のケースではどうなりますか?Oozie を使用してシェルを開始すると、シェルはhadoopJVM で実行されるコマンドを開始します。最大ヒープ サイズを設定する必要が あるのは、その組み込み JVMです。


簡単に言えば、シェルを実行する YARN コンテナーに 32GB を ( 経由でoozie.launcher.mapreduce.map.memory.mb) 割り当てる場合、シェル内の Java コマンドが 28GB を超えるヒープを消費しないようにする必要があります (安全のために)。

運が良ければ、env 変数を 1 つ設定するだけでうまくいきます。

export HADOOP_OPTS=-Xmx28G
hadoop distcp ...........

hadoop-env.sh運が悪ければ、複雑な優先順位を使用して JVM によって解釈されるように、さまざまな環境変数をさまざまな設定 (目に見えてあなたを嫌っている人々によって、あなたが知ることさえできない init スクリプトで設定) と混合する混乱全体をアンラップする必要があります。ルール。楽しむ。どこを掘り下げるかについてのヒントについては、その非常に古い投稿をのぞいてみてください。

于 2016-12-19T21:41:27.157 に答える