如何创建一个可以对并发访问者生存的PHP计数器



我用PHP开发了一个非常简单的计数器。它按预期工作,但偶尔会重置为零。不知道为什么。我怀疑这可能与并发访客有关,但如果我是正确的,我不知道如何防止这种情况发生。这是代码:

function updateCounter($logfile) {
$count = (int)file_get_contents($logfile);
$file = fopen($logfile, 'w');
if (flock($file, LOCK_EX)) {
$count++ ;
fwrite($file, $count);
flock($file, LOCK_UN);
}
fclose($file);
return number_format((float)$count, 0, ',', '.') ;
}

提前谢谢。

锁定文件上的

file_get_contents可能会得到一个"false";(==0(,并且日志文件可能在写入时再次解锁。

经典的比赛条件。。。

由于file_get_contents((在访问先前锁定的文件时可能返回false,因此fwrite((可能会写入0或1,从而将计数器重置为零。

因此,我们尝试在锁定成功后读取计数器文件。


function updateCounter($logfile) {
//$count = (int)file_get_contents($logfile);
if(file_exists($logfile)) {
$mode = 'r+';     
} else {
$mode = 'w+';             
}
//
$file = fopen($logfile, $mode);             
//
if (flock($file, LOCK_EX)) {
//
// read counter file:
//
$count = (int) fgets($file);
$count++ ;
//
// point to the beginning of the file:
//
rewind($file);
fwrite($file, $count);
flock($file, LOCK_UN);
}
fclose($file);
return number_format((float)$count, 0, ',', '.') ;
}
//
$logfile = "counter.log";
echo updateCounter($logfile);

请参阅上的用户说明https://www.php.net/manual/en/function.flock.php。

我会在文件中附加一个字符,并在文件内容上使用strlen来获得命中率。请注意,您的文件会随着时间的推移而变得很大,但这可以通过cronjob轻松解决,该cronjob可以对其进行汇总并将其缓存到另一个只读文件中。

您也可以使用!is_writeable,并检查它是否已锁定,如果是,您可以错过命中或等待while循环直到它可写。虽然很狡猾,但很管用。这取决于每一次点击的价值,以及你想在这个柜台上投入多少精力。

最新更新