在 PHP 个请求之间递增变量

Incrementing variable between PHP requests

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

但是,我使用的特定 SOAP 服务要求每个请求都包含一个唯一的 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缓存中是否存在key,设置为0,否则apc_inc失败,returnsfalse

如果您有多服务器应用程序,您可以将增量 ID 存储在 Memcache/Redis 中(需要 运行 附加服务):

$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);

如果您调用 memcache_increment 与 APC 相同的情况,如果密钥尚不存在,它将失败。

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

最后我就是这样实现的。在考虑了各种选项之后,数据库和各种缓存选项似乎有点矫枉过正。此外,缓存、cookie 和会话似乎被设计为相对临时的,而我实际上是在寻找一种非易失性解决方案。

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

此示例在读取和更新值之前获取文件的独占锁。如果它达到最大整数,它会重置。然后等待 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);

如果你想简单地递增,你可以使用会话变量来实现:

/**
 * 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'));