cas
(Workermanバージョン>=3.3.0が必要です)
bool \GlobalData\Client::cas(string $key, mixed $old_value, mixed $new_value)
アトミックな置き換えで、$new_valueで$old_valueを置き換えます。
現在のクライアントが最後に値を取得した後に、そのkeyに対応する値が他のクライアントによって変更されていない場合のみ、値を記録できます。
パラメータ
$key
キーです。(例:$global->abc、abcがキー)
$old_value
古いデータ
$new_value
新しいデータ
戻り値
置き換えが成功した場合はtrueを返し、そうでない場合はfalseを返します。
説明:
複数のプロセスが同時に同じ共有変数を操作する場合、競合の問題を考慮する必要があります。
例えば、AとBの2つのプロセスが同時にユーザーリストにメンバーを追加する場合。
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);