>  기사  >  데이터 베이스  >  PHP+redis는 잠금 및 잠금 해제 작업을 구현합니다.

PHP+redis는 잠금 및 잠금 해제 작업을 구현합니다.

尚
앞으로
2020-06-20 16:55:063926검색

PHP+redis는 잠금 및 잠금 해제 작업을 구현합니다.

비즈니스 배경: 동시 작업으로 인해 발생하는 Redis 데이터의 더러운 읽기를 방지하기 위해 룸 체스 및 카드 게임에 잠금이 필요합니다. 예를 들어 룸에 입장하기 위해 사용자를 추가하는 작업을 추가합니다. 동시성의 경우, RoomUsers는 더티 읽기 현상을 겪게 됩니다.

해결책: 한 번에 하나의 클라이언트만 룸에서 작동할 수 있도록 룸을 잠그고 다른 동시 클라이언트는 대기합니다. 즉, ----- 잠금을 차단합니다. PHP+redis는 잠금 및 잠금 해제 작업을 구현합니다.

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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 segmentfault.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제