cas
(Requires Workerman version >= 3.3.0)
bool \GlobalData\Client::cas(string $key, mixed $old_value, mixed $new_value)
Reemplazo atómico, reemplaza $old_value
con $new_value
.
Sólo puede escribir el valor si, después de que el cliente actual haya obtenido el valor por última vez, el valor asociado a esa clave no ha sido modificado por otro cliente.
Parámetros
$key
Clave. (Por ejemplo, si es $global->abc
, entonces abc
es la clave)
$old_value
Valor antiguo
$new_value
Nuevo valor
Valor devuelto
Devuelve true si el reemplazo fue exitoso, de lo contrario devuelve false.
Notas:
Cuando múltiples procesos operan simultáneamente sobre una misma variable compartida, a veces es necesario considerar problemas de concurrencia.
Por ejemplo, los procesos A y B agregan un miembro a la lista de usuarios al mismo tiempo.
La variable de lista de usuarios para los procesos A y B es actualmente $global->user_list = array(1,2,3)
.
El proceso A modifica la variable $global->user_list
y agrega el usuario 4.
El proceso B modifica la variable $global->user_list
y agrega el usuario 5.
El proceso A establece la variable como $global->user_list = array(1,2,3,4)
con éxito.
El proceso B establece la variable como $global->user_list = array(1,2,3,5)
con éxito.
En este punto, la variable establecida por el proceso B sobrescribe la variable establecida por el proceso A, causando la pérdida de datos.
Esto se debe a que la lectura y la escritura no son operaciones atómicas, lo que resulta en problemas de concurrencia.
Para resolver este tipo de problemas de concurrencia, se puede utilizar la interfaz de reemplazo atómico (cas).
Antes de cambiar un valor, la interfaz cas verifica si otro proceso ha modificado ese valor basado en $old_value
.
Si ha habido modificaciones, el valor no se reemplaza y devuelve false. De lo contrario, se reemplaza y devuelve true.
Consulte el siguiente ejemplo.
Nota:
En algunos casos, es aceptable que los datos compartidos sean sobrescritos concurrentemente, como el precio más alto actual en un sistema de subastas o el inventario actual de un producto.
Ejemplo
$global = new GlobalData\Client('127.0.0.1:2207');
// Inicializar la lista
$global->user_list = array(1,2,3);
// Añadir de forma atómica un valor a user_list
do
{
$old_value = $new_value = $global->user_list;
$new_value[] = 4;
}
while(!$global->cas('user_list', $old_value, $new_value));
var_export($global->user_list);