我使用的是 Hadoop 1.0.3。
我将日志写入 HDFS 中的 Hadoop 序列文件,在每组日志后调用syncFS(),但我从不关闭该文件(除非我执行每日滚动)。
我想保证的是,当文件仍在写入时,读者就可以使用该文件。
我可以通过 FSDataInputStream 读取序列文件的字节,但如果我尝试使用 SequenceFile.Reader.next(key,val),它会在第一次调用时返回 false。
我知道数据在文件中,因为我可以使用 FSDataInputStream 或 cat 命令读取它,并且我 100% 确定调用了syncFS()。
我检查了namenode和datanode日志,没有错误或警告。
为什么 SequenceFile.Reader 无法读取我当前正在写入的文件?
您无法确保读取完全写入数据节点侧的磁盘。您可以在文档中看到这一点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.
因此它基本上用当前信息更新名称节点的块映射并将数据发送到数据节点。由于您无法将数据刷新到数据节点上的磁盘,而是直接从数据节点读取数据,因此您会遇到数据在某处缓冲且无法访问的时间范围。因此,您的序列文件读取器会认为数据流已完成(或为空),并且无法读取向反序列化过程返回 false 的其他字节。
如果块被完全接收,则数据节点将数据写入磁盘(它是预先写入的,但不能从外部读取)。因此,一旦达到块大小或文件已提前关闭并最终确定块,您就可以从文件中读取数据。这在分布式环境中完全有意义,因为你的编写者可能会死而无法正确完成一个块——这是一个一致性问题。
因此,解决方法是使块大小非常小,以便更频繁地完成块。但这不是那么有效,我希望您应该清楚您的要求不适合 HDFS。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)