ConFoo 2025

Memcached::cas

(PECL memcached >= 0.1.0)

Memcached::casСравнивает и устанавливает значение для записи

Описание

public Memcached::cas(
    string|int|float $cas_token,
    string $key,
    mixed $value,
    int $expiration = 0
): bool

Memcached::cas() осуществляет проверку и установку значения записи, новое значение будет сохранено, только если другие клиенты не обновили его со времени последнего обращения этим клиентом. Эта проверка осуществляется с помощью параметра cas_token, который представляет собой 64-битное значение присвоенное существующей записи сервером memcache. Обратитесь к документации метода 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 {
/* fetch IP list and its token */
$ips = $m->get('ip_block', null, $cas);
/* if list doesn't exist yet, create it and do
an atomic add which will fail if someone else already added it */
if ($m->getResultCode() == Memcached::RES_NOTFOUND) {
$ips = array($_SERVER['REMOTE_ADDR']);
$m->add('ip_block', $ips);
/* otherwise, add IP to the list and store via compare-and-swap
with the token, which will fail if someone else updated the list */
} else {
$ips[] = $_SERVER['REMOTE_ADDR'];
$m->cas($cas, 'ip_block', $ips);
}
} while (
$m->getResultCode() != Memcached::RES_SUCCESS);

?>

Смотрите также

  • Memcached::casByKey() - Сравнивает и устанавливает значение для записи на конкретном сервере

Добавить

Примечания пользователей 4 notes

up
2
abodera at gmail dot com
14 years ago
Watch out!

When using binary protocol, the expected result after cas() is 21 (Memcached::RES_END).

For example, to make the above example #1 work with binary protocol, use the following:
<?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);
?>
up
2
sparcbr at gmail dot com
8 years ago
Do not check command success in a while loop with something like


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

Memcached::RES_SERVER_ERROR or anything like this and your script will loop forev
up
1
Haravikk
7 years ago
I'm not sure whether this remains true in the newer versions of the Memcached module (v3.0 onwards) but in the version shipped with PHP 5.6 the return value and result code when using this method with OPT_BINARY_PROTOCOL enabled are entirely useless.

Setting a value successful may return true, with a result code of RES_END, but it may also return true with a result code of RES_SUCCESS.

However, *unsuccessfully* setting a value likewise seems to return true and RES_SUCCESS, effectively rendering this function's return value useless with the binary protocol enabled as it is impossible to distinguish success from failure.

If you need to rely on the return value of this method then I strongly recommend disabling the binary protocol under PHP 5.6, as in its current state the common memcached module is too broken otherwise for CAS usage.

Hopefully someone else can weigh in on whether this is still broken in newer versions or not.
up
1
php at sergentet dot fr
7 years ago
To prevent a perpetual loop on any Memcached error, you can add a simple counter :

$security_count = 0;

do {
//[]....
$security_loop++
if ($security_loop > 10) {
break; //( or return "your return value" on a function )
}
} while ($m->getResultCode() != Memcached::RES_SUCCESS);
To Top