This article mainly introduces the locking and unlocking of php redis, which has certain reference value. Now I share it with everyone. Friends in need can refer to it
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:
In the case of concurrency, get RoomUsers will have dirty reads;
Solution idea: Lock the room to realize that only one room can be read at a time Allow one client to operate while other concurrent clients wait; that is, ----- blocking lock;
Lock: There are several redis locking methods: incr , set, setnx, hSetnx, you can refer to this article: Several implementations of redis locking
Here I use the set method
$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: Of course you have to unlock it after the operation. If you don’t unlock it, you have to wait at least 3 seconds;
Use delete to delete the key to unlock; but there is a pitfall here, you cannot use delete directly, because it is assumed that client01 has obtained the lock, and after adding the user to enter the room The process time exceeds 3 seconds. At this time, client02 will also obtain the lock and set 3S. 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.
// 将用户添加进房间 $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);
For details, you can also read this article: The correct posture to unlock the Redis lock
There is also documentation on PHP operating redis: PhpRedis contains explanations of the set() and eval() functions
Note: When using lua script here, php.ini needs to open system functions such as shell_exec()
The above code is for reference only! !
The above is the entire content of this article. I hope it will be helpful to everyone's study. For more related content, please pay attention to the PHP Chinese website!
Related recommendations:
Methods and parameter comments for PHP operating Beanstalkd
Intranet penetration application Spike implemented by PHP Refactoring completed
The above is the detailed content of Locking and unlocking of php redis. For more information, please follow other related articles on the PHP Chinese website!