7

在大型 php 应用程序中写入文件的最佳方法是什么。可以说每秒需要大量写入。最好的方法是如何解决这个问题。

我可以打开文件并附加数据吗?或者我应该打开、锁定、写入和解锁。

文件会发生什么,需要写入其他数据。这个活动会丢失,还是会被保存。如果这将被保存将停止应用程序。

如果你去过,谢谢你的阅读!

4

7 回答 7

9

这是一个简单的例子,突出了同时写的危险:

<?php
for($i = 0; $i < 100; $i++) {
 $pid = pcntl_fork();
 //only spawn more children if we're not a child ourselves
 if(!$pid)
  break;
}

$fh = fopen('test.txt', 'a');

//The following is a simple attempt to get multiple threads to start at the same time.
$until = round(ceil(time() / 10.0) * 10);
echo "Sleeping until $until\n";
time_sleep_until($until);

$myPid = posix_getpid();
//create a line starting with pid, followed by 10,000 copies of
//a "random" char based on pid.
$line = $myPid . str_repeat(chr(ord('A')+$myPid%25), 10000) . "\n";
for($i = 0; $i < 1; $i++) {
    fwrite($fh, $line);
}

fclose($fh);

echo "done\n";

如果追加是安全的,您应该得到一个包含 100 行的文件,所有这些行大约 10,000 个字符长,并且以整数开头。有时,当你运行这个脚本时,这正是你会得到的。有时,一些附加会发生冲突,但是会被破坏。

您可以找到损坏的行grep '^[^0-9]' test.txt

这是因为文件追加仅在以下情况下是原子的

  1. 您进行了一次 fwrite() 调用
  2. 并且 fwrite() 小于 PIPE_BUF (大约 1-4k)
  3. 然后你写入一个完全符合 POSIX 的文件系统

如果您在日志追加期间对 fwrite 进行了多次调用,或者您写入的内容超过了 4k,那么所有的赌注都将被取消。

现在,至于这是否重要:您是否可以在重负载的情况下在日志中有一些损坏的行?老实说,大多数时候这是完全可以接受的,您可以避免文件锁定的开销。

于 2010-03-02T02:07:51.217 回答
6

我确实有高性能的多线程应用程序,其中所有线程都在写入(附加)到单个日志文件。到目前为止,没有注意到任何问题,每个线程每秒写入多次,并且没有任何丢失。我认为只是附加到大文件应该没有问题。但是如果你想修改已经存在的内容,尤其是并发性——我会选择锁定,否则可能会发生大混乱......

于 2010-03-01T20:32:05.387 回答
4

如果并发是一个问题,那么您真的应该使用数据库。

于 2010-03-01T20:28:01.777 回答
1

如果你只是写日志,也许你需要看看 syslog 函数,因为syslog提供了一个 api。您还应该将写入委托给专门的后端并以异步方式完成工作吗?

于 2010-03-29T13:46:24.550 回答
1

这些是我的 2p。

除非出于特定原因需要一个唯一的文件,否则我会避免将所有内容附加到一个巨大的文件中。相反,我会按时间和维度包装文件。可以为此定义几个配置参数(wrap_time 和 wrap_size)。

另外,我可能会引入一些缓冲以避免等待写操作完成。

可能 PHP 不是最适合这种操作的语言,但它仍然是可能的。

于 2010-03-29T13:57:33.013 回答
0

使用羊群()

看到这个问题

于 2010-03-01T20:28:15.600 回答
-3

如果您只需要追加数据,PHP 应该可以,因为文件系统应该负责同时追加。

于 2010-03-01T20:29:05.443 回答