PHP文件编写中的竞争条件
因此,我有一个脚本,用于接受和处理来自其他脚本和/或应用程序的请求。但是,我的脚本必须完成的任务之一是为每个请求分配一个唯一的、连续的“ID” 例如,假设应用程序A向我的脚本发出1000个请求,同时,应用程序B向我的脚本发出500个请求。我必须给他们1500个唯一的序列号,比如2001~3500 但是,它们之间的顺序并不重要,因此我可以给它们这样的数字:PHP文件编写中的竞争条件,php,concurrency,race-condition,Php,Concurrency,Race Condition,因此,我有一个脚本,用于接受和处理来自其他脚本和/或应用程序的请求。但是,我的脚本必须完成的任务之一是为每个请求分配一个唯一的、连续的“ID” 例如,假设应用程序A向我的脚本发出1000个请求,同时,应用程序B向我的脚本发出500个请求。我必须给他们1500个唯一的序列号,比如2001~3500 但是,它们之间的顺序并不重要,因此我可以给它们这样的数字: #2001 for 1st request from A (henceforth, A1) #2002 for A2 #2003 for B1
#2001 for 1st request from A (henceforth, A1)
#2002 for A2
#2003 for B1
#2004 for A3
#2005 for B2
...and so on...
private function get_last_id()
{
// Check if lock file exists...
while (file_exists("LAST_ID_LOCKED")) {
// Wait a little bit before checking again
usleep(1000);
}
// Create the lock file
touch("LAST_ID_LOCKED");
// Create the ID file for the first time if required
if (!file_exists("LAST_ID_INDICATOR")) {
file_put_contents("LAST_ID_INDICATOR", 0);
}
// Get the last ID
$last_id = file_get_contents("LAST_ID_INDICATOR");
// Update the last ID
file_put_contents("LAST_ID_INDICATOR", $last_id + 1);
// Delete the lock file
unlink("LAST_ID_LOCKED");
return $last_id;
}
我尝试创建一个存储该号码的文件和一个单独的锁文件,其功能如下:
#2001 for 1st request from A (henceforth, A1)
#2002 for A2
#2003 for B1
#2004 for A3
#2005 for B2
...and so on...
private function get_last_id()
{
// Check if lock file exists...
while (file_exists("LAST_ID_LOCKED")) {
// Wait a little bit before checking again
usleep(1000);
}
// Create the lock file
touch("LAST_ID_LOCKED");
// Create the ID file for the first time if required
if (!file_exists("LAST_ID_INDICATOR")) {
file_put_contents("LAST_ID_INDICATOR", 0);
}
// Get the last ID
$last_id = file_get_contents("LAST_ID_INDICATOR");
// Update the last ID
file_put_contents("LAST_ID_INDICATOR", $last_id + 1);
// Delete the lock file
unlink("LAST_ID_LOCKED");
return $last_id;
}
然而,此代码将创建一个竞争条件,如果我向他们发送1500个请求,最后一个ID将有相当多的丢失(例如,仅达到3211个,而不是3500个)
我也尝试过这样使用flock,但没有效果:
private function get_last_id()
{
$f = fopen("LAST_ID_INDICATOR", "rw");
while (true) {
if (flock($f, LOCK_SH)) {
$last_id = fread($f, 8192);
flock($f, LOCK_UN);
fclose($f);
break;
}
usleep($this->config["waiting_time"]);
}
$f = fopen("LAST_ID_INDICATOR", "rw");
while (true) {
if (flock($f, LOCK_SH)) {
$last_id = fread($f, 8192);
$last_id++;
ftruncate($f, 0);
fwrite($f, $last_id);
flock($f, LOCK_UN);
fclose($f);
break;
}
usleep($this->config["waiting_time"]);
}
return $last_id;
}
那么,我还能做些什么来寻找这种情况的解决方案呢
注意:由于服务器的限制,我只能使用PHP5.2,没有信号量之类的东西。由于似乎没有人给出答案,我会给你一个可能的解决方案 使用作为解决方案的一部分 编辑:如果您不需要保留顺序,则过滤器锁定的效果会更好 显然,这在实现上会有它自己的挑战,但值得一试,如果你做对了,它可能只是为你想做的事做了一件事 既然你提到了信号量,我想你知道足够的知识来理解这个概念
这可以在“.”的第2章中找到。如果您可以访问具有锁定功能的数据库,则可以使用该数据库。例如,对于具有骨架PHP代码的MySQL:
TABLENAME
(COLUMNNAME INTEGER)ENGINE=MyISAM'
excecuteSql($sql)TABLENAME
SETCOLUMNNAME
=0'
executeSql($sql)TABLENAME
'
if($result=mysqli_查询($link,$sql)){
}
$sql='UPDATETABLENAME
SETCOLUMNNAME
=COLUMNNAME
+1'
executeSql($sql)
$sql=“选择释放锁('numberLock')”
executeSql($sql)您可以使用
uniqid()
函数生成id,它基于微时间。文件的用途是什么?Uniqid不会这样做,因为它是随机的,我需要数字是连续的。LAST_ID_指示符的用途只是存储最后(最大)的ID号。uniqid()
并非完全随机,虽然不是顺序的,但每次调用函数都会以升序生成ID。使用hexdec()
将其转换为十进制以了解我的意思。是的,这与我的问题非常接近,谢谢。现在主要的问题是如何在PHP中实现它…这是一个复杂的部分,您需要阅读更多关于上面2个锁的内容,创建这样的锁将非常复杂,没有人会在上面发布代码。