Java FSDataInputStream是否仅限于创建时已写入的字节?

Java FSDataInputStream是否仅限于创建时已写入的字节?,java,hadoop,io,streaming,hdfs,Java,Hadoop,Io,Streaming,Hdfs,所以我试图理解HDFS中的一些行为。我的目标是设置一个配置,在写入任何字节之前,我打开一个FSDataOutputStream到某个位置,然后让我的应用程序的其他部分立即打开一个FSDataInputStream到该位置 这样做的想法是,当我将字节写入FSDataOutputStream、刷新它们并调用“sync()”时,任何能够访问同一位置的FSDataInputStream的人都应该能够读取这些字节 可悲的是,它似乎不是这样工作的。当我以这种方式设置代码时,会发生以下情况: FSDataOu

所以我试图理解HDFS中的一些行为。我的目标是设置一个配置,在写入任何字节之前,我打开一个FSDataOutputStream到某个位置,然后让我的应用程序的其他部分立即打开一个FSDataInputStream到该位置

这样做的想法是,当我将字节写入FSDataOutputStream、刷新它们并调用“sync()”时,任何能够访问同一位置的FSDataInputStream的人都应该能够读取这些字节

可悲的是,它似乎不是这样工作的。当我以这种方式设置代码时,会发生以下情况:

FSDataOutputStream writer = fs.create(new Path("/foo/bar"));
FSDataInputStream reader = fs.open(new Path("/foo/bar"));
writer.write(new byte[]{1, 1, 1, 1, 1});
writer.flush();
writer.sync();
System.out.println(reader.available()); // writes '0'
FSDataOutputStream writer = fs.create(new Path("/foo/bar"));
writer.write(new byte[] {1, 1, 1, 1, 1});
writer.flush();
writer.sync();
FSDataInputStream reader = fs.open(new Path("/foo/bar"));
System.out.println(reader.available()); // writes '5'
然而!当我以这种方式设置代码时,会发生以下情况:

FSDataOutputStream writer = fs.create(new Path("/foo/bar"));
FSDataInputStream reader = fs.open(new Path("/foo/bar"));
writer.write(new byte[]{1, 1, 1, 1, 1});
writer.flush();
writer.sync();
System.out.println(reader.available()); // writes '0'
FSDataOutputStream writer = fs.create(new Path("/foo/bar"));
writer.write(new byte[] {1, 1, 1, 1, 1});
writer.flush();
writer.sync();
FSDataInputStream reader = fs.open(new Path("/foo/bar"));
System.out.println(reader.available()); // writes '5'
最后,我运行的第三个测试是:

FSDataOutputStream writer = fs.create(new Path("/foo/bar"));
writer.write(new byte[] {1, 1, 1, 1, 1});
writer.flush();
writer.sync();
FSDataInputStream reader = fs.open(new Path("/foo/bar"));
writer.write(new byte[] {2, 2, 2, 2, 2});
writer.flush();
writer.sync();
System.out.println(reader.available()); // writes '5'
我的结论是,FSDataInputStream的作用域总是限制在创建输入流时已经写入的字节内。这有什么办法吗?我在输入流或类似的东西上没有看到“refresh()”方法


我真的,真的很想知道我是否有办法强迫输入流更新它的可用字节。我错过了什么?我做错了什么?这样做是错误的吗?

据我所知,
DFSInputStream
仅在打开时以及在尝试读取块时遇到错误时刷新其已定位块的列表。因此,无论您在输出流中执行什么操作,输入流都不会被更新


如果您试图实现一个单一生产者/多消费者系统,您可能会考虑使用zookeeper之类的工具进行协调。

您应该学习所学内容并给出自己的答案:)一旦我确定我得到了所有有用的反馈,我将得到。Argh。我想知道创建一个替代的输入流实现来公开这个刷新方法是否有意义?我想他们没有那样做几乎肯定有原因,我只是希望我知道那是什么。我希望能够将HDFS用作一种总线,在这种总线中,任何东西都可以在输入时看到任何东西的输出-\我的猜测是,他们可以实现重置,但这样做并不真正符合其预期的一次写入/多次读取范式。复制和大数据块带来的开销对于增量读/写来说可能太大了。是的,我正在阅读DFSInputStream源代码,我知道您来自哪里。尽管如此,“invalidateBlock(LocatedBlock block)”方法还是非常有用的。只需强制它在下次读取时从namenode获取它。但是,这可能也是限制namenode的一个很好的方法。嗯,现在接受这个答案。经过更多的挖掘,看起来即使是新添加的hflush和hsync方法也不会强制DFInputStream使其缓存块无效。可能有一种方法可以强制执行错误读取,这将使缓存无效并强制刷新-如果我有时间,我将对此进行调查,并将在有效的情况下发布更新。