我有一个网站,在同一时刻,可能有多个用户同时写入同一个文件。我的代码示例如下。
PHP 5.6.20
<?php
$root=realpath($_SERVER["DOCUMENT_ROOT"]);
$var=time()."|";
echo $var."<br/>";
$filename=$root."/Testing/Testing/test1.txt";
$myfile=fopen($filename,"a");
fwrite($myfile,$var);
fclose($myfile);
$myfile=fopen($filename,"r");
$contents = fread($myfile, filesize($filename));
echo $contents;
fclose($myfile);
?>
我在PHP中读到,如果多个用户试图在同一个文件中写入同一个文件,则可能会出现数据损坏,我当然不希望有一个可能导致数据损坏的代码从长远来看。
我试图在我的浏览器上几乎同时运行上面的代码来模拟多个用户同时写入同一个文件,并且它没有产生任何错误或任何数据损坏到写入的文件,但是我仍然不确定未来的数据损坏。
我读到我可以使用flock来确保2个用户不能同时写入文件,但是由于我测试了上面的代码并且它没有产生数据损坏,我不确定是否应该更新我的代码与flock或只是保持原样。
我的问题是:
1)上述代码是否有可能破坏其写入的文件?
2)如果是,使用flock会解决这个问题吗?如果是的话,我应该如何在上面的代码中实现flock?修改
我知道这种不确定性可以通过使用数据库来解决,但对于这种情况,最好使用纯文本,所以请不要建议我使用数据库。
提前感谢。
答案 0 :(得分:0)
您需要将保存机制从简单文件更改为包含事务的任何数据库。
答案 1 :(得分:0)
如果两个脚本同时尝试写入文件。 fopen()函数在文件上调用时,不会阻止同一个文件被另一个脚本打开,这意味着你可能会发现一个脚本从另一个文件读取文件,或者更糟糕的是,两个脚本写入同时存档。所以使用flock()是好的。 您可以在http://www.hackingwithphp.com/8/11/0/locking-files-with-flock上获得更多帮助。 对于您的代码,您可以使用flock()作为
<?php
$root=realpath($_SERVER["DOCUMENT_ROOT"]);
$var=time()."|";
echo $var."<br/>";
$filename=$root."/Testing/Testing/test1.txt";
$myfile=fopen($filename,"a");
if (flock($myfile, LOCK_EX)) {
fwrite($myfile,$var);
flock($fp, LOCK_UN); // unlock the file
} else {
// flock() returned false, no lock obtained
print "Could not lock $filename!\n";
}
fclose($myfile);
$myfile=fopen($filename,"r");
if (flock($myfile, LOCK_EX)) {
$contents = fread($myfile, filesize($filename));
echo $contents;
flock($fp, LOCK_UN); // unlock the file
} else {
// flock() returned false, no lock obtained
print "Could not lock $filename!\n";
}
fclose($myfile);
?>
答案 2 :(得分:0)
我不熟悉羊群,但我的第一个想法是锁定或排队机制。如果不必使用写入的数据或查看用户,那么工作队列将是最佳选择。将数据写入基于redis或memcached的系统,sql或其他类型的排队系统,或者只将具有有趣内容的唯一带时间戳的文件转储到工作人员可以按升序聚合到maste文件中的目录中。
对于写入数据触发用户需要获取报告或结果,响应或其他反馈的用例,如果您无法重新构建异步,则锁定可能是方式堆叠与最终的一致性。在了解并发用户的负载和数量,服务器数量等情况下,也很难知道。
答案 3 :(得分:0)
对于许多编程语言中的许多Web应用程序来说,这是一个常见的理论问题。
答案是肯定的,它会导致麻烦。但是,这是一个非常理论上的问题,如果您要添加到文件中的内容不是很大,并且如果您没有大量流量。今天的操作系统和文件系统得到了很好的优化(缓存,懒惰写入等),当你在使用它们后立即关闭文件句柄时,它很可能不会发生。
如果遇到错误(在使用其他语言编写PHP / catch异常之前检查访问权限),可以添加类似缓冲区的内容,并在延迟一段时间后重试或将缓冲区写入临时文件并将其合并另一个过程 - 你有几种可能性。
是的,flock()是一个可以用于这些目的的功能,但我认为,这已经过度设计了。