如何在大型php应用程序中写入文件(多个问题)

时间:2010-03-01 20:24:07

标签: php file append flock

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

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

该文件将会发生什么,需要编写其他数据。这项活动会丢失,还是会被保存。如果保存这将停止申请。

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

7 个答案:

答案 0 :(得分: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

找到损坏的行

这是因为file append is only atomic if

  1. 您进行一次fwrite()调用
  2. 并且fwrite()小于PIPE_BUF(大约1-4k)
  3. 并且您写入完全符合POSIX的文件系统
  4. 如果您在日志追加期间多次拨打fwrite,或者您的写入次数超过4k,则所有投注均已关闭。

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

答案 1 :(得分:6)

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

答案 2 :(得分:4)

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

答案 3 :(得分:1)

如果您只是编写日志,可能需要查看syslog函数,因为syslog提供了api。 您还应该将写入委托给专用的后端并在异步的maneer中完成工作吗?

答案 4 :(得分:1)

这些是我的2p。

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

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

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

答案 5 :(得分:0)

使用flock()

请参阅此question

答案 6 :(得分:-3)

如果您只需要附加数据,那么PHP应该没问题,因为文件系统应该同时处理附加内容。