我写了这个计数器,它跟踪一个网站的是/否,它工作得很好,问题是某些文件在写作时搞砸了。例如:它将从126变为27.脚本从我编写的iOS应用程序调用,因此很可能有多个连接同时修改文件,我认为这是导致问题的原因。我不是一个真正的PHP人员,所以我希望能够深入了解什么可以使代码变得更好并处理多个同时连接。
<?php
$yes_file = 'yes.txt';
$no_file = 'no.txt';
$yes_count = file_get_contents($yes_file);
$no_count = file_get_contents($no_file);
if ($_GET['result'])
{
if( strcmp($_GET['result'], "YES") ) {
$no_count+=1;
file_put_contents($no_file, $no_count);
}
else {
$yes_count+=1;
file_put_contents($yes_file, $yes_count);
}
}
$total = $yes_count + $no_count;
echo "{\"yescount\":" . $yes_count.",";
echo "\"nocount\":" . $no_count.",";
echo "\"total\":" . $total."}";
?>
谢谢!
答案 0 :(得分:1)
首先,我建议使用数据库系统来跟踪计数器。
关于您的问题,在读取 - 更新 - 写入周期期间flock()文件会有所帮助。这可能会阻止race conditions。
答案 1 :(得分:1)
这应该更有效率。
仅供参考,数据库在递增时对行/表进行写锁定,这与我在下面所做的相同,因此数据库不是解决方案 - 解决方案是写锁定(通过数据库或通过PHP)。你可以使用flock
,但我发现它太乱了,所以我只是用一个临时文件来完成它。
我的代码唯一的问题是,如果服务器在这个脚本的中间崩溃,那么写锁定将保持不变(MySQL有时会出现这个问题)。我通常通过在文件中写time()
并检查它是否超过一小时或更长时间来解决这个问题。但在你的情况下,这可能是不必要的。
<?php
// Your variables
$yes_file = 'yes.txt';
$no_file = 'no.txt';
if (isset($_GET['result']))
{
// Write lock
while(file_exists('temporaryfile')) usleep(100000);
file_put_contents('temporaryfile','1');
$yes_count = (int)file_get_contents($yes_file);
$no_count = (int)file_get_contents($no_file);
// Increment
if ($_GET['result']=='YES')
{
$yes_count++;
file_put_contents($yes_file, $yes_count);
}
else
{
$no_count++;
file_put_contents($no_file, $no_count);
}
// Unlock
unlink('temporaryfile');
}
else // No need for any lock so just get the vars
{
$yes_count = (int)file_get_contents($yes_file);
$no_count = (int)file_get_contents($no_file);
}
$total = $yes_count + $no_count;
echo "{\"yescount\":$yes_count,\n\"nocount\":$no_count,\n\"total\":$total}";