首先,考虑一下这个CustomWriter类:
public final class CustomWriter {
private final SequenceFile.Writer writer;
CustomWriter(Configuration configuration, Path outputPath) throws IOException {
FileSystem fileSystem = FileSystem.get(configuration);
if (fileSystem.exists(outputPath)) {
fileSystem.delete(outputPath, true);
}
writer = SequenceFile.createWriter(configuration,
SequenceFile.Writer.file(outputPath),
SequenceFile.Writer.keyClass(LongWritable.class),
SequenceFile.Writer.valueClass(ItemWritable.class),
SequenceFile.Writer.compression(SequenceFile.CompressionType.BLOCK, new DefaultCodec()),
SequenceFile.Writer.blockSize(1024 * 1024),
SequenceFile.Writer.bufferSize(fileSystem.getConf().getInt("io.file.buffer.size", 4 * 1024)),
SequenceFile.Writer.replication(fileSystem.getDefaultReplication(outputPath)),
SequenceFile.Writer.metadata(new SequenceFile.Metadata()));
}
public void close() throws IOException {
writer.close();
}
public void write(Item item) throws IOException {
writer.append(new LongWritable(item.getId()), new ItemWritable(item));
}
}
我要做的是使用Item
类型对象的异步流。使用者可以引用CustomWriter
实例。然后,它会为其收到的每个项调用CustomWriter#write
方法。当流结束时,调用CustomWriter#close
方法关闭编写器。
正如您所看到的,我只创建了一个编写器,它开始追加到一个全新的文件中。因此,毫无疑问this不是原因。
我还应该注意,我目前正在使用MiniDFSCluster
按照说明here在单元测试环境中运行此功能。如果我在非单元测试环境中运行它(即没有MiniDFSCluster
),它似乎工作正常。
当我尝试回读文件时,我看到的是最后写入的Item
个对象N次(其中N是流中接收的项目总数)。这是一个例子:
sparkContext.hadoopFile(path, SequenceFileInputFormat.class, LongWritable.class, ItemWritable.class)
.collect()
.forEach(new BiConsumer<>() {
@Override
public void accept(Tuple2<LongWritable, ItemWritable> tuple) {
LongWritable id = tuple._1();
ItemWritable item = tuple._2();
System.out.print(id.get() + " -> " + item.get());
}
});
这将打印出类似这样的内容:
...
1234 -> Item[...]
1234 -> Item[...]
1234 -> Item[...]
...
我做错了什么,或者这是使用MiniDFSCluster
的副作用吗?
答案 0 :(得分:1)
Writable
(例如LongWritable, ItemWritable
)。收到记录时,Writable
通常只会替换其内容,您只会收到相同的Writable
对象。如果要将它们收集到数组中,则应将它们复制到新对象。