Home > Database > Redis > body text

PHP+redis implements locking and unlocking operations

Release: 2020-06-20 16:55:06
forward
3953 people have browsed it

PHP+redis implements locking and unlocking operations

Business background: Locks are needed in room chess and card games to prevent dirty reading of redis data caused by concurrent operations; for example, adding the action of a user entering the room:

PHP+redis implements locking and unlocking operations

In the case of concurrency, get RoomUsers will have dirty reads;

Solution: lock the room to allow only one client to operate in a room at a time, and other concurrent clients The end is waiting; that is ----- blocking lock;

Lock: There are several redis locking methods: incr, set, setnx, hSetnx, you can refer to this article: Several redis locking methods A kind of implementation

Recommendation:PHP video tutorial

Here I use set this way

$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); // ['李四', '王五', '张三']
Copy after login

Unlocking: Of course you have to unlock it after the operation, no You have to wait at least 3 seconds to unlock;

To unlock, use delete to delete the key; but there is a pitfall here. Delete cannot be used directly, because it is assumed that client01 obtains the lock and the time exceeds 3 seconds during the process of adding users to the room. , at this time client02 will also obtain the lock and set 3S, and then when client01 completes the operation and delete key, the lock set by client02 will be deleted;

It is recommended to use lua code to perform deletion, because lua execution is atomic sex.

// 将用户添加进房间
$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);
Copy after login

For more related knowledge, please pay attention to redis introductory tutorialcolumn

The above is the detailed content of PHP+redis implements locking and unlocking operations. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:segmentfault.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template