【问题标题】:How to reduce the number of file writes when there are multiple threads?多线程时如何减少文件写入次数?
【发布时间】:2011-05-25 16:58:24
【问题描述】:

情况是这样的。

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

为了保持配置,我发现每次您对其进行更改时,都会将包含配置对象列表的通用对象序列化为一个文件。

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

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

那么,有没有办法减少实际文件写入的次数,但仍保证所有更改最终都被序列化?

任何建议表示赞赏

【问题讨论】:

  • 为什么要将配置存储为序列化对象?
  • 这不是我的选择,设计师认为它会很好很简单,不幸的是,他不在身边看到结果,我负责“让它对 QA 人员足够快”。 ..任何方式我都不能在不久的将来改变它,因为设计已经被批准并且功能测试已经结束。改变它的根源以使用db4o 或 JavaDB 将根据政治将我们带回开发阶段......并且至少延迟 3 周。我讨厌现在为如此糟糕的设计负责。

标签: java performance serialization file-io concurrency


【解决方案1】:

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

后台线程可以使用ScheduledExecutorService 进行调度。

IMO,最好使用数据库。你不能使用像Java DBH2HSQLDB 这样的嵌入式数据库吗?这些数据库支持并发访问,也可以在崩溃的情况下保证数据的一致性。

【讨论】:

  • 谢谢!将写入更改为每隔几秒而不是一秒钟写入多次,这对这些请求的响应时间产生了奇迹,正如预期的那样,它们不再等待序列化完成。
  • 很高兴知道。我希望你能尽快改变这个设计,使用这样的系统真的很糟糕。
【解决方案2】:

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

【讨论】:

  • 我尝试将写入分成不同的文件,它减少了响应时间,不幸的是,正如您所指出的,在峰值负载期间,它也成为 io-bound 并且响应延迟很多。 (但不如单个文件时那么多)。
【解决方案3】:

一种方法是做 Lucene 所做的事情,而不是真正覆盖旧文件,而是编写一个只包含“更新”的新文件。这取决于您的更新是否具有关联性,但无论如何通常都是如此。

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

为了让这个想法更加相关,请考虑上面的数字是否是某种记录。 “3”可以翻译为“添加三个新记录”,“-2”可以翻译为“删除这两个记录”。

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

【讨论】:

    猜你喜欢
    • 2012-06-27
    • 2015-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多