ConFoo 2025

Memcached::cas

(PECL memcached >= 0.1.0)

Memcached::casComparar e intercambiar un ítem

Descripción

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

Memcached::cas() realiza una operación "comprobar y establecer" ('cas' por sus siglas en inglés), de forma que el ítem será guardado solamente si ningún otro cliente lo actualizó desde la última vez que este cliente lo obtuvo. La comprobación se realiza mediante el parámetro cas_token, el cual es un valor único de 64 bit asignado al ítem existente por memcache. Ver la documentación de los métodos Memcached::get*() para saber cómo obtener este token. Observar que el token está representado como un valor de tipo double debido a las limitaciones de espacio para valores integer de PHP.

Parámetros

cas_token

El valor único asociado con el ítem existente. Generado por memcache.

key

La clave en la que se guardará el valor.

value

El valor a guardar.

expiration

Tiempo de expiración, que por defecto es 0. Ver Tiempos de expiración para más información.

Valores devueltos

Devuelve true en caso de éxito o false en caso de error. Memcached::getResultCode() devolverá Memcached::RES_DATA_EXISTS si el ítem que se trata de guardar ha sido modificado desde la última vez que se obtuvo.

Ejemplos

Ejemplo #1 Ejemplo de Memcached::cas()

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

do {
/* obtener la lista de direcciones IP y sus token */
$ips = $m->get('ip_block', null, $cas);
/* si la lista no existe aún, crear una y realizar
un añadido atómico que fallará si alguien ya añadió un valor */
if ($m->getResultCode() == Memcached::RES_NOTFOUND) {
$ips = array($_SERVER['REMOTE_ADDR']);
$m->add('ip_block', $ips);
/* en caso contrario, añadir la IP a la lista y guardar vía comparar-e-intercambiar
con el token, que fallará si alguien ya actualizó la lista */
} else {
$ips[] = $_SERVER['REMOTE_ADDR'];
$m->cas($cas, 'ip_block', $ips);
}
} while (
$m->getResultCode() != Memcached::RES_SUCCESS);

?>

Ver también

add a note

User Contributed Notes 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