在PHP请求之间递增变量


Incrementing variable between PHP requests

我正在编写一个PHP脚本,根据请求,该脚本将使用各种参数调用SOAP服务,其中一些参数取自请求。

然而,我正在使用的特定SOAP服务要求每个请求都包含一个唯一的ID,在这种情况下,需要为每个请求增加ID。它不能基于时间,并且对于每个请求都必须是唯一的,但是如果跳过值也没关系。

使用MySQL数据库来存储单个值似乎有些过头了。我曾想过将其存储并加载到一个文件中,但比赛条件的问题突然浮现在脑海中。

我确实可以完全访问服务器,这将是专门用于此任务的某种Linux风格。

有没有一种简单的方法可以实现这一点?

在任何新请求使用PHP的time()函数获得增量值之前,因为每个请求的时间都是唯一的。

 $increment_id = time();

如果您的应用程序是单服务器,您可以尝试使用在APC中存储增量ID

$key = 'soap_service_name';
if (!apc_exists($key)) {
    apc_store($key, 0);
}
$id = apc_inc($key);

您需要检查APC缓存中是否存在密钥并设置0,否则apc_inc失败并返回false

如果你有多服务器应用程序,你可以在Memcache/Redis中存储增量id(需要运行额外的服务):

$key = 'soap_service_name';
$memcache = memcache_connect('memcache_host', 11211);
if (!empty(memcache_exists($memcache, $key))) {
    memcache_set($memcache, 0);
}
$id = memcache_increment($memcache, $key);

和APC的情况相同,若你们调用memcache_increment,若密钥还不存在,它就会失败。

如果这个增量ID应该永久存储,Redis会更有用,因为它可以用磁盘写入所有数据。这是一种带有磁盘写入功能的Memcache。

这就是我最终实现这一目标的方式。在考虑了各种选项后,数据库和各种缓存选项似乎有点过头了。此外,缓存、cookie和会话似乎是相对临时的,而我实际上在寻找一种非易失性的解决方案。

这就是我提出的一个简单的文件锁定解决方案。我没有意识到PHP可以处理文件锁,但当我发现这一点时,这似乎是最好的方法。

此示例在读取和更新值之前获取文件的独占锁。如果它达到最大int,它就会重置。然后等待5秒钟。如果脚本被快速连续调用几次,请注意,每个请求都将等待前一个请求的锁释放后再继续。

好的是,因为这是PHP,不存在的文件,无效的内容等,只会导致值默认为零。

<?php
$f = fopen('sequence_num.txt', 'r+');
echo "Acquiring lock<br />'n";
flock($f, LOCK_EX);
echo "Lock acquired, updating value<br />'n";
$num = intval(fread($f, strlen(PHP_INT_MAX)));
echo "Old val = " . $num;
if ($num >= PHP_INT_MAX) {
    $num = 0;
} else {
    $num++;
}
echo " New val = " . $num;
echo "<br />Waiting 5 seconds<br />'n";
rewind($f);
ftruncate($f, 0);
fwrite($f, $num);
sleep(5);
echo "Releasing lock<br />'n";
flock($f, LOCK_UN);
fclose($f);

如果您愿意使用浮点值作为唯一值,请使用:

$unique_id = microtime(true);

如果你想简单地增加,你可以使用会话var:来完成

/**
 * Get session increment.
 *
 * @param string $id
 * @param int $default
 * @return int
 */
function get_increment($id, $default = 0)
{
    if (array_key_exists($id, $_SESSION)) $_SESSION[$id] += 1;
    else $_SESSION[$id] = $default;
    return $_SESSION[$id];
}
var_dump(get_increment('unique_id'));