PHP Conference Japan 2024

Memcached::cas

(PECL memcached >= 0.1.0)

Memcached::cas比较并交换一个项目

描述

public Memcached::cas(
    字符串|整数|浮点数 $cas_token,
    字符串 $key,
    混合类型 $value,
    整数 $expiration = 0
): 布尔值

Memcached::cas() 执行“检查并设置”操作,以便仅当自此客户端上次获取该项目以来没有其他客户端更新该项目时,才会存储该项目。检查是通过 cas_token 参数进行的,该参数是 memcache 分配给现有项目的唯一 64 位值。有关如何获取此令牌,请参阅 Memcached::get*() 方法的文档。请注意,由于 PHP 整数空间的限制,令牌表示为浮点数。

参数

cas_token

与现有项目关联的唯一值。由 memcache 生成。

key

存储值的键。

value

要存储的值。

expiration

过期时间,默认为 0。有关更多信息,请参阅 过期时间

返回值

成功时返回 true,失败时返回 false。如果尝试存储的项目自上次获取以来已被修改,则 Memcached::getResultCode() 将返回 Memcached::RES_DATA_EXISTS

示例

示例 #1 Memcached::cas() 示例

<?php
$m
= new Memcached();
$m->addServer('localhost', 11211);

do {
/* 获取 IP 列表及其令牌 */
$ips = $m->get('ip_block', null, $cas);
/* 如果列表尚不存在,则创建它并执行
原子添加,如果其他人已添加它,则原子添加将失败 */
if ($m->getResultCode() == Memcached::RES_NOTFOUND) {
$ips = array($_SERVER['REMOTE_ADDR']);
$m->add('ip_block', $ips);
/* 否则,将 IP 添加到列表中并通过比较和交换存储
使用令牌,如果其他人更新了列表,则此操作将失败 */
} else {
$ips[] = $_SERVER['REMOTE_ADDR'];
$m->cas($cas, 'ip_block', $ips);
}
} while (
$m->getResultCode() != Memcached::RES_SUCCESS);

?>

参见

添加注释

用户贡献的注释 4 条注释

abodera at gmail dot com
14 年前
注意!

使用二进制协议时,cas() 后的预期结果为 21 (Memcached::RES_END)。

例如,要使上述示例 #1 与二进制协议一起使用,请使用以下内容
<?php
$m
= new Memcached();
$m->addServer('localhost', 11211);
$m->setOption(Memcached::OPT_BINARY_PROTOCOL,true)

// [...]

} else {
$ips[] = $_SERVER['REMOTE_ADDR'];
$m->cas($cas, 'ip_block', $ips);
}
} while (
$m->getResultCode() != Memcached::RES_END);
?>
sparcbr at gmail dot com
8 年前
不要使用类似以下内容的 while 循环检查命令是否成功


$memCached->getResultCode() != Memcached::RES_SUCCESS

Memcached::RES_SERVER_ERROR 或类似内容,您的脚本将永远循环
Haravikk
7 年前
我不确定这在较新版本的 Memcached 模块(v3.0 及更高版本)中是否仍然适用,但在 PHP 5.6 附带的版本中,使用此方法启用 OPT_BINARY_PROTOCOL 时的返回值和结果代码完全没用。

成功设置值可能会返回 true,结果代码为 RES_END,但也可能返回 true,结果代码为 RES_SUCCESS。

但是,*不成功*设置值似乎也返回 true 和 RES_SUCCESS,有效地使此函数的返回值在启用二进制协议时变得毫无用处,因为无法区分成功和失败。

如果需要依赖此方法的返回值,我强烈建议在 PHP 5.6 下禁用二进制协议,因为在其当前状态下,普通的 memcached 模块对于 CAS 使用来说太糟糕了。

希望其他人可以权衡这在较新版本中是否仍然存在问题。
php at sergentet dot fr
7 年前
为了防止在任何 Memcached 错误上出现永久循环,您可以添加一个简单的计数器

$security_count = 0;

do {
//[]....
$security_loop++
if ($security_loop > 10) {
break; //(或者在函数中返回“您的返回值”)
}
} while ($m->getResultCode() != Memcached::RES_SUCCESS);
To Top