【发布时间】:2010-09-21 10:21:49
【问题描述】:
我有一个场景,一个 PHP 进程每秒大约 3 次写入一个文件,然后几个 PHP 进程正在读取这个文件。
这个文件本质上是一个缓存。我们的网站有一个非常坚持的轮询,对于不断变化的数据,我们不希望每个访问者每次轮询时都访问数据库,所以我们有一个每秒读取数据库 3 次的 cron 进程,处理数据,并将其转储到轮询客户端可以读取的文件中。
我遇到的问题是,有时打开文件进行写入需要很长时间,有时甚至长达 2-3 秒。我假设发生这种情况是因为它被读取(或某些东西)锁定,但我没有任何确凿的方法来证明这一点,另外,根据我从文档中了解到的情况, PHP 不应该锁定任何东西。 这种情况每 2-5 分钟发生一次,因此很常见。
在代码中,我没有进行任何类型的锁定,而且我几乎不在乎该文件的信息是否损坏、读取失败或数据是否更改读到一半。 但是,我确实在意,如果写入它需要 2 秒,本质上,因为必须每秒发生三次的过程现在跳过了几个节拍。
我正在用这段代码编写文件:
$handle = fopen(DIR_PUBLIC . 'filename.txt', "w");
fwrite($handle, $data);
fclose($handle);
我正在直接阅读它:
file_get_contents('filename.txt')
(它没有作为静态文件直接提供给客户端,我收到了一个常规的 PHP 请求,它读取文件并用它做一些基本的事情)
该文件大约 11kb,因此读/写不需要太多时间。不到 1 毫秒。
这是发生问题时的典型日志条目:
Open File: 2657.27 ms
Write: 0.05984 ms
Close: 0.03886 ms
不确定它是否相关,但读取发生在常规 Web 请求中,通过 apache,但写入是由 Linux 的 cron 执行的常规“命令行”PHP 执行,它不通过 Apache。
您有什么想法会导致打开文件出现如此大的延迟吗?
关于我可以在哪里寻找帮助我查明实际原因的任何指示?
或者,您能想到我可以做些什么来避免这种情况吗?例如,我希望能够为 fopen 设置 50 毫秒的超时时间,如果它没有打开文件,它就会向前跳过,让下一次运行 cron 来处理它。
再次重申,我的首要任务是让 cron 每秒跳动三次,其他一切都是次要的,因此非常欢迎任何想法、建议和任何事情。
谢谢!
丹尼尔
【问题讨论】:
-
这取决于文件系统如何实现锁以及 PHP 是否尊重它们。如果您以读取模式打开文件,则不应创建锁定。但是,您可以将“w”(写入)替换为“a”(仅附加)
-
会改变模式以追加避免锁定吗?
-
是否写入一个不同名称的文件,然后重命名为公共缓存文件名?
-
马克,我想尝试一下,但我担心删除现在需要我很长时间才能打开的文件会同样糟糕。它在我的尝试清单上