cas
(требуется версия Workerman >= 3.3.0)
bool \GlobalData\Client::cas(string $key, mixed $old_value, mixed $new_value)
Атомарная замена, заменяет$old_value на $new_value.
Значение может быть записано только в том случае, если после последнего чтения его значение не было изменено другими клиентами.
Параметры
$key
Ключ. (например $global->abc; здесь abc — это ключ)
$old_value
Старые данные
$new_value
Новые данные
Возвращаемое значение
Возвращает true в случае успешной замены, иначе возвращает false.
Описание:
При одновременной работе нескольких процессов с одной общей переменной нужно учитывать проблемы с параллелизмом.
Например, два процесса A и B одновременно добавляют участника в список пользователей.
В данный момент для двух процессов пользовательский список равен $global->user_list = array(1,2,3).
Процесс A работает с переменной $global->user_list, добавляя пользователя 4.
Процесс B работает с переменной $global->user_list, добавляя пользователя 5.
Процесс A устанавливает переменную $global->user_list = array(1,2,3,4) успешно.
Процесс B устанавливает переменную $global->user_list = array(1,2,3,5) успешно.
В этом случае переменная, установленная процессом B, перекрывает переменную, установленную процессом A, что приводит к потере данных.
Это происходит из-за того, что чтение и запись не являются атомарными операциями, что вызывает проблемы с параллелизмом.
Чтобы решить такие проблемы, можно использовать интерфейс атомарной замены cas.
Интерфейс cas перед изменением значения
проверяет по$old_value, было ли это значение изменено другими процессами,
если изменено, то замена не происходит, возвращает false. В противном случае замена происходит, возвращает true.
Смотрите пример ниже.
Внимание:
Некоторые общие данные можно параллельно перезаписывать без проблем, например, текущая максимальная ставка на аукционах или текущее количество товаров на складе и т.п.
Пример
$global = new GlobalData\Client('127.0.0.1:2207');
// Инициализация списка
$global->user_list = array(1,2,3);
// Атомарное добавление значения в 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);