ホームページ  >  記事  >  バックエンド開発  >  PHP Redisのロックとロック解除

PHP Redisのロックとロック解除

不言
不言オリジナル
2018-07-06 16:59:503336ブラウズ

この記事では主にphp redisのロックとロック解除について紹介しますが、参考値があるのでみんなに共有します。困っている友達は参考にしてください

php redisはロックとロック解除の操作を実装します

ビジネスの背景: ルーム チェスやカード ゲームでは、同時操作による Redis データの不正な読み取りを防ぐために、ロックが必要です (たとえば、ユーザーがルームに入るアクションを追加するなど)。

PHP Redisのロックとロック解除

同時実行の場合、get RoomUsers はダーティ読み取りを行うことになります;


ソリューションのアイデア : ルームをロックして、それを実現するだけです一度に 1 つのルームを読み取ることができます 他の同時クライアントが待機している間、1 つのクライアントが動作できるようにします; つまり、----- ブロック ロック;


Lock: いくつかありますRedis ロック メソッド: incr 、 set、setnx、hSetnx。この記事を参照してください: Redis ロックのいくつかの実装

ここでは set メソッドを使用します

$roomId = $_GET['roomId'];
$user = $_GET['user'];             // '张三'
$key = "LockRoom:{$roomId}";
$value = $roomId.uniqid();
$ex = 3;
// 如果 $key 不存在的话,就设置 $key 的值为 $value,且有效期为 3s; 
// return TRUE / FALSE
while(true){
    $res  = $this->redis->set($key, $value, ['nx', 'ex' => $ex]);
    if($res) { break; }
    usleep(5000);
}

// 将用户添加进房间
$roomUsers = $this->redis->get("Room:{$roomId}:Users"); // ['李四', '王五']
$roomUsers[] = $user;
$this->redis->set("Room:{$roomId}:Users", $roomUsers); // ['李四', '王五', '张三']


Unlocking : もちろん、操作後にロックを解除する必要があります。ロックを解除しない場合は、少なくとも 3 秒待つ必要があります。 ロックを解除するキーを削除するには、delete を使用します。しかし、ここに落とし穴があります。 client01 がロックを取得していると想定されているため、削除を直接使用することはできません。ユーザーを追加してルームに入室すると、処理時間が 3 秒を超えます。このとき、client02 もロックを取得して 3S を設定します。 client01 が操作を完了してキーを削除すると、client02 によって設定されたロックが削除されます;
Lua の実行はアトミックであるため、削除を実行するには lua コードを使用することをお勧めします。

// 将用户添加进房间
$roomUsers = $this->redis->get("Room:{$roomId}:Users"); // ['李四', '王五']
$roomUsers[] = $user;
$this->redis->set("Room:{$roomId}:Users", $roomUsers); // ['李四', '王五', '张三']

// lua 脚本解锁
// 先判断 key的值是否为 value, TRUE 才会删除, 所以 $value 的设计要有随机唯一性
$script = 'if redis.call("get",KEYS[1]) == ARGV[1]
then
    return redis.call("del",KEYS[1])
else
    return 0
end ';
$this->redis->eval($script, array($key , $value), 1);

詳細については、次の記事もお読みください: Redis ロックを解除するための正しい姿勢

PHP の Redis 操作に関するドキュメントもあります: PhpRedis には set() と eval の説明が含まれています() 関数

注: ここで lua スクリプトを使用する場合、php.ini はshell_exec() などのシステム関数を開く必要があります。

上記のコードは参照のみです。 !

上記がこの記事の全内容です。皆様の学習に少しでもお役に立てれば幸いです。その他の関連コンテンツについては、PHP 中国語 Web サイトをご覧ください。

関連する推奨事項:

PHP 操作 Beanstalkd のメソッドとパラメーターのコメント

PHP リファクタリングによって実装されたイントラネット侵入アプリケーション Spike が完了しました

以上がPHP Redisのロックとロック解除の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。