비즈니스 배경: 동시 작업으로 인해 발생하는 Redis 데이터의 더러운 읽기를 방지하기 위해 룸 체스 및 카드 게임에 잠금이 필요합니다. 예를 들어 룸에 입장하기 위해 사용자를 추가하는 작업을 추가합니다. 동시성의 경우, RoomUsers는 더티 읽기 현상을 겪게 됩니다.
해결책: 한 번에 하나의 클라이언트만 룸에서 작동할 수 있도록 룸을 잠그고 다른 동시 클라이언트는 대기합니다. 즉, ----- 잠금을 차단합니다.
Lock: redis lock 여러 가지 방법이 있습니다: incr, set, setnx, hSetnx. 이 문서를 참조하세요: redis locking의 여러 구현권장:PHP 비디오 튜토리얼
여기에서는 이 방법을 설정합니다$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초를 기다려야 합니다. 잠금을 해제하려면 삭제를 사용하여 키를 삭제해야 합니다. .클라이언트01이 잠금을 획득한 것으로 가정하므로 삭제를 직접 사용할 수 없습니다. 방에 입장할 사용자를 추가하는 과정에서 클라이언트02도 잠금을 획득하고 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는 잠금 및 잠금 해제 작업을 구현합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!