This article mainly introduced about PHP Redis locking and unlock, has a certain reference value, now share to everyone, have the need for friends can refer to
Php+redis implement lock and unlock operation
Business background : In room chess game need to use a lock to prevent the concurrent operation caused by the Redis data dirty read problem, such as adding the user into the room action:
In the case of concurrency, get roomusers will have a dirty read phenomenon;
Solution : Lock the room to achieve a room to allow only one client operation at a time, the other concurrent clients wait; that is-----blocking lock;
Locking : There are several types of Redis lock: incr, set, Setnx, Hsetnx, can refer to this article: several implementations of Redis plus lock
Here I use set this way
$roomId = $_get[' Roomid '); $user = $_get[' user ']; ' Zhang San ' $key = "lockroom:{$roomId}"; $value = $roomId. Uniqid (); $ex = 3;//If $key does not exist, the value of the set $key is $value and the validity period is 3s; Return True/falsewhile (TRUE) { $res = $this->redis->set ($key, $value, [' NX ', ' ex ' = + $ex]); if ($res) {break;} Usleep (5000);} Add user into Room $roomusers = $this->redis->get ("room:{$roomId}:users"); [' John Doe ', ' Harry '] $roomUsers [] = $user; $this->redis->set ("room:{$roomId}:users", $roomUsers); [' John Doe ', ' Harry ', ' Zhang San ']
unlock : After the operation of course to unlock, do not unlock at least to wait 3 seconds;
Unlock Delete key with delete; But there is a pit, not directly with the delete, because assuming that CLIENT01 acquired the lock, in the process of adding a user to enter the room for more than 3 seconds, this time client02 will also acquire the lock and set 3S, and then when the client01 operation is finished delete key, The client02 set lock is removed;
It is recommended to perform the removal with LUA code, because Lua execution is atomic.
Add user into Room $roomusers = $this->redis->get ("room:{$roomId}:users"); [' John Doe ', ' Harry '] $roomUsers [] = $user; $this->redis->set ("room:{$roomId}:users", $roomUsers); [' John Doe ', ' Harry ', ' Zhang San ']//lua script unlock//First determine if key is value, TRUE is deleted, so $value design to have random uniqueness $script = ' If Redis.call ("Get", keys[ 1] = = Argv[1]then return redis.call ("Del", Keys[1]) Else return 0end '; $this->redis->eval ($script, Array ($key, $value), 1);
You can also look at this article: Unlock the correct posture of the Redis lock
and the PHP Operation Redis Documentation: Phpredis contains the set (), eval () function explanation
Note: Using LUA scripts here php.ini requires Open shell_exec () and other system functions
The above code is only for reference!!
The above is the whole content of this article, I hope that everyone's learning has helped, more relevant content please pay attention to topic.alibabacloud.com!