1

Hadoop 1.0.3 を使用しています。

Hadoop シーケンス ファイルのログを HDFS に書き込みます。ログの各束の後に syncFS() を呼び出しますが、ファイルを閉じることはありません (毎日のローリングを実行している場合を除く)。

私が保証したいのは、ファイルがまだ書き込まれている間、ファイルが読者に利用可能であることです。

FSDataInputStream を介してシーケンス ファイルのバイトを読み取ることができますが、SequenceFile.Reader.next(key,val) を使用しようとすると、最初の呼び出しで false が返されます。

FSDataInputStream または cat コマンドを使用してデータを読み取ることができるため、データがファイル内にあることがわかり、syncFS() が呼び出されることは 100% 確実です。

namenode と datanode のログを確認しましたが、エラーや警告はありませんでした。

SequenceFile.Reader が現在書き込まれているファイルを読み取れないのはなぜですか?

4

4 に答える 4

3

読み取りがデータノード側のディスクに完全に書き込まれることを保証することはできません。DFSClient#DFSOutputStream.sync()これは、次の状態のドキュメントで確認できます。

  All data is written out to datanodes. It is not guaranteed that data has
  been flushed to persistent store on the datanode. Block allocations are
  persisted on namenode.

したがって、基本的には現在の情報でネームノードのブロックマップを更新し、データをデータノードに送信します。データノードのディスクにデータをフラッシュすることはできませんが、データノードから直接読み取るため、データがバッファリングされてアクセスできない時間枠に到達します。したがって、sequencefile リーダーは、データストリームが終了した (または空になった) と見なし、追加のバイトを読み取ることができず、逆シリアル化プロセスに false を返します。

ブロックが完全に受信されると、データノードはデータをディスクに書き込みます (事前に書き込まれますが、外部から読み取ることはできません)。したがって、ブロックサイズに達するか、ファイルが事前に閉じられてブロックがファイナライズされると、ファイルから読み取ることができます。これは、分散環境では完全に理にかなっています。なぜなら、ライターが死んでブロックを適切に終了できない可能性があるためです。これは一貫性の問題です。

したがって、修正は、ブロックサイズを非常に小さくして、ブロックがより頻繁に終了するようにすることです。しかし、それはあまり効率的ではありません。あなたの要件が HDFS に適していないことが明確になることを願っています。

于 2013-01-17T12:30:29.893 に答える
1

SequenceFile.Reader が書き込まれているファイルの読み取りに失敗する理由は、ファイルの長さを使用してその魔法を実行するためです。

最初のブロックが書き込まれている間、ファイルの長さは 0 のままで、ブロックがいっぱいになったときにのみ更新されます (デフォルトでは 64MB)。次に、2 番目のブロックが完全に書き込まれるまで、ファイル サイズは 64MB のままです。

つまり、直接 FSInputStream を使用して生データを読み取ることができる場合でも、SequenceFile.Reader を使用してシーケンス ファイル内の最後の不完全なブロックを読み取ることはできません。

ファイルを閉じるとファイルの長さも修正されますが、私の場合はファイルを閉じる前に読み取る必要があります。

于 2013-01-31T13:57:34.737 に答える
-1

同様の問題に直面しました。これを修正した方法は次のとおりです

于 2013-03-05T19:19:54.217 に答える