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

Posted

技术标签:

【中文标题】如何在大型 php 应用程序中写入文件(多问)【英文标题】:How to write to file in large php application(multiple questions) 【发布时间】:2011-01-22 11:06:20 【问题描述】:

在大型 php 应用程序中写入文件的最佳方式是什么。可以说每秒需要大量写入。最好的方法是什么。

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

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

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

【问题讨论】:

【参考方案1】:

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

【讨论】:

我正在写入日志文件。对数据库的写入已经很重了,所以对于日志文件,我只想写入文件。 文件也应该是并发的。【参考方案2】:

使用flock()

看到这个question

【讨论】:

【参考方案3】:

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

【讨论】:

标准 linux 文件系统肯定“照顾”同时追加。举一个简单的例子来说明为什么会这样,想象一下:两个进程在彼此的毫秒内打开同一个文件,并以每秒 100 兆的速度附加一个 gig 的数据——这意味着每个进程的写入时间为 10 秒。文件系统如何确保写入不重叠?是否应该缓冲来自第二个进程的数据,直到第一个进程完成? 好吧,既然你使用了绝对荒谬的例子,我只想说:PHP 无法每秒追加 100 兆,它也无法处理这些数据。虽然,你可以对这样的假设情况是正确的,但现实是另一回事,正如上面所说的那样,附加只是有效的。吃那个。 发布了一个简单的真实示例,显示了多个同时附加的相互冲突。 ***.com/questions/2358818/…【参考方案4】:

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

【讨论】:

+1。我每天都会在我的 apache 访问日志中获得重叠的条目,因此在高负载时肯定会发生一些损失。但是对于一个日志文件,被破坏的那几行真的无关紧要,而且它们当然不值得文件锁定的开销。 @Laimoncijus,你的意思是追加是原子的吗?【参考方案5】:

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

<?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:

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

如果您在日志追加期间多次调用 fwrite,或者写入超过 4k,则所有赌注都将被取消。

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

【讨论】:

【参考方案6】:

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

【讨论】:

【参考方案7】:

这些是我的 2p。

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

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

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

【讨论】:

以上是关于如何在大型 php 应用程序中写入文件(多问)的主要内容,如果未能解决你的问题,请参考以下文章

大型 PHP 会话减慢 Web 应用程序

如何将大型多维数组部分写入 HDF5 文件?

我如何使用python写入大型txt文件的每个字符?

大型 PHP 应用程序的依赖关系图

使用来自企业应用程序的 PHP 从 MySQL 数据生成大型 Excel 文件

在PHP中,如何实现写入或创建另1个PHP文件?