hadoop fs コマンドで dfs にコピーする際のリトライ回数を増やすには

前提

  • CDH2u3
  • NotReplicatedYetException が発生してコピーに失敗する場合。具体的には以下みたいなログが出力される場合。
12/10/08 11:17:47 INFO hdfs.DFSClient: org.apache.hadoop.ipc.RemoteException: org.apache.hadoop.hdfs.server.namenode.NotReplicatedYetException: Not replicated yet:${HDFS上のファイルのパス}
        at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.getAdditionalBlock(FSNamesystem.java:1268)
        at org.apache.hadoop.hdfs.server.namenode.NameNode.addBlock(NameNode.java:469)
        at sun.reflect.GeneratedMethodAccessor12.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.hadoop.ipc.RPC$Server.call(RPC.java:512)
        at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:966)
        at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:962)
        at java.security.AccessController.doPrivileged(Native Method)
        at javax.security.auth.Subject.doAs(Subject.java:396)
        at org.apache.hadoop.ipc.Server$Handler.run(Server.java:960)

        at org.apache.hadoop.ipc.Client.call(Client.java:740)
        at org.apache.hadoop.ipc.RPC$Invoker.invoke(RPC.java:221)
        at $Proxy0.addBlock(Unknown Source)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.hadoop.io.retry.RetryInvocationHandler.invokeMethod(RetryInvocationHandler.java:82)
        at org.apache.hadoop.io.retry.RetryInvocationHandler.invoke(RetryInvocationHandler.java:59)
        at $Proxy0.addBlock(Unknown Source)
        at org.apache.hadoop.hdfs.DFSClient$DFSOutputStream.locateFollowingBlock(DFSClient.java:2932)
        at org.apache.hadoop.hdfs.DFSClient$DFSOutputStream.nextBlockOutputStream(DFSClient.java:2807)
        at org.apache.hadoop.hdfs.DFSClient$DFSOutputStream.access$2000(DFSClient.java:2087)
        at org.apache.hadoop.hdfs.DFSClient$DFSOutputStream$DataStreamer.run(DFSClient.java:2274)
12/10/08 11:17:47 WARN hdfs.DFSClient: NotReplicatedYetException sleeping ${HDFS上のファイルのパス} retries left 4

対応方法

HDFS クラスタの負荷が高いためか、コピー対象を書き込むための次のブロックが取得できない場合に発生する例外のようです。 dfs.client.block.write.locateFollowingBlock.retries オプションを指定することでリトライ回数を増やせます。以下みたいな感じで指定します。

hadoop fs -D dfs.client.block.write.locateFollowingBlock.retries=10 -copyFromLocal  URI
  • デフォルトは 5 回になっていて、実装箇所は DFSOutputStream#locateFollowingBlock です。
    • リトライする際にスリープ間隔を延ばす実装になっていて、初期値は 400 ミリ秒です。リトライする毎に 2 倍にします。
    • 最初に処理を開始してからリトライを繰り返し、 5 秒を超えると以下の warn ログを出力するようになります。
      • Waiting for replication for ${処理開始からの経過秒数} seconds
  • CDH2u3 で動作することは確認済みです。
    • CDH3u5 はソースが残っていることは確認しましたが、動作確認は行なっていません。

時間が掛かってもいいからより確実にコピーしたい場合はリトライ回数を増やしてみるといいかもしれません。実際、今の職場では増やして運用してます。