Java 当存在多个线程时,如何减少文件写入的数量?

Java 当存在多个线程时,如何减少文件写入的数量?,java,performance,serialization,file-io,concurrency,Java,Performance,Serialization,File Io,Concurrency,情况是这样的 在我被分配到mantain的一个Java Web应用程序中,我被要求在QA期间改进压力测试的一般响应时间。这个web应用程序不使用数据库,因为它应该是轻巧和简单的。(我不能改变这个决定) 为了持久化配置,我发现每次对其进行更改时,包含配置对象列表的常规对象都会序列化为文件 使用Jmeter,我发现在给定的测试用例中,有2个请求占用了大部分时间。这两个请求都会添加或更改某些配置对象。由于对文件的访问必须同步,当许多用户更改配置时,文件必须在几秒钟内完全写入几次,请求等待文件写入 我认

情况是这样的

在我被分配到mantain的一个Java Web应用程序中,我被要求在QA期间改进压力测试的一般响应时间。这个web应用程序不使用数据库,因为它应该是轻巧和简单的。(我不能改变这个决定)

为了持久化配置,我发现每次对其进行更改时,包含配置对象列表的常规对象都会序列化为文件

使用Jmeter,我发现在给定的测试用例中,有2个请求占用了大部分时间。这两个请求都会添加或更改某些配置对象。由于对文件的访问必须同步,当许多用户更改配置时,文件必须在几秒钟内完全写入几次,请求等待文件写入

我认为所有这些序列化根本没有必要,因为我们一次又一次地重写大多数对象,每个请求中的更改都是针对一个对象的,但是每次都将文件作为一个整体写入

那么,有没有一种方法可以减少实际文件写入的数量,但仍然可以保证所有更改最终都被序列化


任何建议

一个选项是在内存中进行更改,并在后台保留一个线程,以给定的间隔运行,并将更改刷新到磁盘。请记住,在崩溃的情况下,您将丢失未刷新的数据

后台线程可以使用调度


依我看,最好使用数据库。你不能使用嵌入式数据库吗?这些数据库支持并发访问,还可以在崩溃时保证数据的一致性。

如果绝对不能使用数据库,显而易见的解决方案是将单个文件分解为多个文件,每个配置对象对应一个文件。它将加快序列化和输出过程,并减少锁争用(更改不同配置对象的请求可能会同时写入其文件,尽管它可能会成为IO绑定)。

一种方法是执行Lucene所做的操作,而不是实际覆盖旧文件,而是编写一个只包含“更新”的新文件. 这取决于您的更新是关联的,但通常情况下都是这样

这个想法是,如果您的旧文件包含“8”,并且您有3个更新,那么您将“3”写入新文件,而新状态为“11”,接下来您将写入“-2”,现在您有“9”。您可以定期聚合旧的和更新的内容。您编写的任何物理文件都不会更新,但一旦不再使用,可能会被删除

为了让这个想法更贴切一些,考虑上面的数字是否是某种类型的记录。“3”可译为“添加三条新记录”;“-2”可译为“删除这两条记录”


Lucene是一个非常成功地使用这种添加式更新策略的项目的例子。

为什么要将配置存储为序列化对象?这不是我的选择,设计师认为这会很好而且简单,不幸的是,他不在现场看结果,我负责“让QA人员能够足够快地完成”。。。无论如何,我不能在不久的将来改变这一点,因为设计已经获得批准,功能测试已经结束。根据政治观点,将其根改为使用或JavaDB将把我们带回开发阶段。。。至少要推迟3周。我讨厌现在对如此糟糕的设计负责。我尝试将写操作划分到不同的文件中,这减少了响应时间,不幸的是,正如您所指出的,在峰值负载期间,它也会受到io限制,响应会延迟很多。(但没有一个文件那么多)谢谢!将写入更改为每几秒钟一次,而不是每秒多次写入,这对这些请求的响应时间产生了奇迹般的效果,正如预期的那样,它们不再等待序列化完成。很高兴知道。我希望你能尽快改变这个设计,使用这样的系统真的很糟糕。