簡體   English   中英

附加到 HDFS 上的文件的推薦方法是什么?

[英]What is the recommended way to append to files on HDFS?

我無法找出一種安全的方法來附加到HDFS文件。

我正在使用一個小型的3-node Hadoop cluster (CDH v.5.3.9 to be specific) 我們的進程是一個multi-threaded (8 threads)的數據管道,它有一個階段將分隔文本行附加到HDFS上專用目錄中的文件。 我正在使用鎖來同步線程對附加數據的緩沖寫入器的訪問。

我的第一個問題是一般地決定方法。

方法 A是打開文件,附加到它,然后對附加的每一行關閉它。 這看起來很慢,而且似乎會產生太多的小塊,或者至少我在各種帖子中看到了一些這樣的情緒。

方法 B是緩存編寫器,但定期刷新它們以確保編寫器列表不會無限增長(目前,管道器處理的每個輸入文件都有一個編寫器)。 這似乎是一種更有效的方法,但我想在一段時間內打開流但受控可能是一個問題,尤其是對於輸出文件閱讀器(?)

除此之外,我真正的問題有兩個。 我正在使用FileSystem Java Hadoop API進行追加,並且間歇性地收到以下 2 個異常:

org.apache.hadoop.ipc.RemoteException: failed to create file /output/acme_20160524_1.txt for DFSClient_NONMAPREDUCE_271210261_1 for client XXX.XX.XXX.XX because current leaseholder is trying to recreate file.

org.apache.hadoop.ipc.RemoteException: BP-1999982165-XXX.XX.XXX.XX-1463070000410:blk_1073760252_54540 does not exist or is not under Constructionblk_1073760252_545 40{blockUCState=UNDER_RECOVERY, primaryNodeIndex=1, replicas=[ReplicaUnderConstruction[[DISK]DS-ccdf4e55-234b-4e17-955f-daaed1afdd92:NORMAL|RBW], ReplicaUnderConst ruction[[DISK]DS-1f66db61-759f-4c5d-bb3b-f78c260e338f:NORMAL|RBW]]}

有人對其中任何一個有任何想法嗎?

對於第一個問題,我嘗試了在這篇文章中討論的檢測邏輯,但似乎沒有幫助。

如果適用,我也對dfs.support.append屬性的作用感興趣。

我獲取文件系統的代碼:

userGroupInfo = UserGroupInformation.createRemoteUser("hdfs"); Configuration conf = new Configuration();
conf.set(key1, val1);
...
conf.set(keyN, valN);
fileSystem = userGroupInfo.doAs(new PrivilegedExceptionAction<FileSystem>() { 
  public FileSystem run() throws Exception { 
   return FileSystem.get(conf);
  }
});

我獲取OutputStream的代碼:

org.apache.hadoop.fs.path.Path file = ...
public OutputStream getOutputStream(boolean append) throws IOException {   
  OutputStream os = null;
  synchronized (file) { 
    if (isFile()) {
      os = (append) ? fs.append(file) : fs.create(file, true);
    } else if (append) {
      // Create the file first, to avoid "failed to append to non-existent file" exception
      FSDataOutputStream dos = fs.create(file);
      dos.close();
      // or, this can be: fs.createNewFile(file);
      os = fs.append(file);
    }
    // Creating a new file
    else { 
      os = fs.create(file);
    }
  }
  return os;
} 

我在 CDH 5.3 / HDFS 2.5.0 上附加了文件。 到目前為止,我的結論如下:

  • 無論我們是通過 HDFS API FileSystem 的同一個實例還是不同的實例寫入數據,都不能有一個專用線程執行每個文件的附加,或多個線程寫入多個文件。
  • 無法刷新(即關閉並重新打開)編寫器; 他們必須保持開放。
  • 最后一項導致偶爾出現的相對罕見的 ClosedChannelException 似乎可以恢復(通過重試追加)。
  • 我們使用帶有阻塞隊列的單線程執行器服務(一個用於附加到所有文件); 每個文件有一個編寫器,編寫器保持打開狀態(直到關閉時處理結束)。
  • 當我們升級到比 5.3 更新的 CDH 時,我們將要重新審視這一點,看看什么線程策略是有意義的:一個且唯一的線程,每個文件一個線程,多個線程寫入多個文件。 此外,我們想看看是否可以/需要定期關閉和重新打開編寫器。
  • 此外,我還看到了以下錯誤,並且能夠通過在客戶端將 'dfs.client.block.write.replace-datanode-on-failure.policy' 設置為 'NEVER' 使其消失。
java.io.IOException: Failed to replace a bad datanode on the existing pipeline due to no more good datanodes being available to try. (Nodes: current=[XXX.XX.XXX.XX:50010, XXX.XX.XXX.XX:50010], original=[XXX.XX.XXX.XX:50010, XXX.XX.XXX.XX:50010]). The current failed datanode replacement policy is DEFAULT, and a client may configure this via 'dfs.client.block.write.replace-datanode-on-failure.policy' in its configuration.
       at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.findNewDatanode(DFSOutputStream.java:969) ~[hadoop-hdfs-2.5.0.jar:?]
       at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.addDatanode2ExistingPipeline(DFSOutputStream.java:1035) ~[hadoop-hdfs-2.5.0.jar:?]
       at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.setupPipelineForAppendOrRecovery(DFSOutputStream.java:1184) ~[hadoop-hdfs-2.5.0.jar:?]
       at org.apache.hadoop.hdfs.DFSOutputStream$DataStreamer.run(DFSOutputStream.java:532) ~[hadoop-hdfs-2.5.0.jar:?] 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM