为什么 hsync() 不刷新我的 hdfs 文件?

Why is hsync() not flushing my hdfs file?

尽管有关于这个主题的所有资源,但我在刷新磁盘上的 hdfs 文件时遇到问题 (hadoop 2.6) 调用 FSDataOutputStream.hsync() 应该可以解决问题,但由于未知原因,它实际上只能使用一次...

这是一个失败的简单单元测试:

@Test
public void test() throws InterruptedException, IOException {
    final FileSystem filesys = HdfsTools.getFileSystem();
    final Path file = new Path("myHdfsFile"); 
    try (final FSDataOutputStream stream = filesys.create(file)) {
        Assert.assertEquals(0, getSize(filesys, file));  
        stream.writeBytes("0123456789");
        stream.hsync();
        stream.hflush();
        stream.flush();
        Thread.sleep(100);
        Assert.assertEquals(10, getSize(filesys, file)); // Works
        stream.writeBytes("0123456789");
        stream.hsync();
        stream.hflush();
        stream.flush();
        Thread.sleep(100);
        Assert.assertEquals(20, getSize(filesys, file)); // Fails, still 10           
    }
    Assert.assertEquals(20, getSize(filesys, file)); // works
}


private long getSize(FileSystem filesys, Path file) throws IOException {
    return filesys.getFileStatus(file).getLen();
}

知道为什么吗?

事实上,hsync()在内部调用没有标志的私有flushOrSync(boolean isSync, EnumSet<SyncFlag> syncFlags),如果提供SyncFlag.UPDATE_LENGTH,长度只会在namenode上更新。

在上面的测试中,用实际读取文件的代码替换 getSize()

private long getSize(FileSystem filesys, Path file) throws IOException {        
    long length = 0;
    try (final  FSDataInputStream input = filesys.open(file)) {
        while (input.read() >= 0) {
            length++;
        }
    }
    return length;
}

要更新大小,您也可以调用(没有适当的 class 类型检查):

((DFSOutputStream) stream.getWrappedStream())).hsync(EnumSet.of(SyncFlag.UPDATE_LENGTH));