我有这个方法:
GenericDatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<GenericRecord>(schema);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BinaryEncoder encoder = EncoderFactory.get().binaryEncoder(baos, null);
public void WriteToFile(Record record) {
this.baos.reset();
try (FileOutputStream fileOut = new FileOutputStream(avroFile, true)) {
datumWriter.write(record, encoder);
encoder.flush();
fileOut.write("RecordStart\n".getBytes());
baos.writeTo(fileOut);
fileOut.write("\nRecordEnd\n".getBytes());
this.baos.flush();
} catch (IOException e) {
logger.error("Error while writing: ", e);
}
}
上面的方法由多个线程调用,每个线程将编写一个 record
介于 RecordStart
以及 RecordEnd
,可能会发生日志交错的情况,即我们将无法在 RecordStart
以及 RecordEnd
所以要避免这种情况,一个解决办法就是 synchronized
但这将导致性能问题,因为我们正在使线程等待。
所以我想要一些建议,这样我们就可以避免多个线程同时写入同一个文件,这可能会导致日志的交错?
1条答案
按热度按时间mnemlml81#
只有当您的操作可以并行化时,您才能从并行处理中获益。我的意思是:
如果您正在写入一个文件,这个特定的计算步骤必须同步完成,即通过
synchronized
或者通过文件锁,否则你会得到混乱的数据。要提高性能,您可以做的是:尽可能减少同步/锁定块,将最后一步(写入)仅保留在同步或锁定块上。除此之外,您可以写入多个文件。
我更喜欢使用文件锁,因为它将使方法更通用。如果你决定扩展它,这样它就可以用来写多个文件。同时它也避免了其他进程使用文件(除了您的程序)。
看看这个问题。
回答具体问题:
所以我想要一些建议,这样我们就可以避免多个线程同时写入同一个文件,这可能会导致日志的交错?
在不损失性能的情况下。。。我认为没有办法。写入文件的本质要求它是连续的。
我见过的大多数系统都将所有日志写入一个文件,它们使用一个队列和一种方法,在队列可以提供的情况下,一条记录一条记录地写入,因此只要系统不不断地接收超过磁盘所能管理的记录数,所有内容最终都会被写入。