ビジネスの背景: ルームのチェスやカード ゲームでは、同時操作による Redis データの不正な読み取りを防ぐためにロックが必要です (たとえば、ユーザーがルームに入るアクションを追加するなど)。
##同時実行の場合、get RoomUsers はダーティ読み取りを行うことになります; 解決策: ルームをロックして、同時に 1 つのルーム内で 1 つのクライアントだけが操作できるようにします。時間、および他の同時クライアント 最後は待機中です; つまり ----- ロックをブロックしています; Lock: Redis のロック方法はいくつかあります: incr、set、setnx、hSetnx。この記事を参照してください。 : いくつかの Redis ロック方法 一種の実装推奨事項:ここではこの方法で設定します$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); // ['李四', '王五', '张三']ロック解除: もちろん、あなたは操作後にロックを解除する必要があります。いいえ、ロックを解除するには少なくとも 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 入門チュートリアル column を参照してください。
以上がPHP+redis はロック操作とロック解除操作を実装しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。