1. Redis lock classification
Redis uses the INCR, SETNX, and SET tables for locking commands
2. The first lock command INCR
If the key does not exist, the value of the key will be initialized to 0 before the INCR operation is performed to add one. If the number returned by the other user is greater than 1, the lock is in use.
Client B also requests the server to obtain the key value of 2, indicating that the lock fails to be obtained. 3. Client A completes the code execution and deletes the lock. Remove lock $redis - > incr ($key); $redis->expire($key, $ttl); // Set the build time to 1 secondCopy the code
3. The second type of lock SETNX
So the idea is, if the key doesn’t exist, set the key to value and if the key already exists, SETNX doesn’t do anything
2. Client B also requests the server to set the key value. If the return fails, it means that the lock fails. $redis->setNX($key, $value); $redis->expire($key, $ttl);Copy the code
4. The third type of lock SET
One problem with both methods is that you need to set the key to expire. So why set the key to expire? If for some reason the request execution unexpectedly exits, causing the lock to be created but not deleted, the lock will remain so that the cache will never be updated again. So we need to add an expiration date to the lock just in case. However, setting with Expire is not an atomic operation. So there are still transactions to ensure atomicity, but there are still some problems, so another one is officially referenced. The use of the SET command itself has included the ability to SET the expiration time since version 2.6.12.
2. Client B also requests the server to set the key value. If the return fails, it means that the lock fails. Remove lock $redis - > set ($key, $value, array (' nx ', 'the ex' = > $TTL)); / / the ex said secondsCopy the code
5. Other questions
Although the previous step has satisfied our requirements, there are other issues to consider, right? 1. What if Redis finds that the lock failed? Interrupt request or loop request? 2. In the case of circular request, if one of them gets the lock, is it easy for others to grab the lock when they get the lock? 3. After the lock expires in advance, client A does not complete execution and client B obtains the lock. When client A finishes execution, will the lock of CLIENT B be deleted when deleting the lock?
6. Solutions
For problem 1: use cyclic requests, cyclic requests to acquire locks
For problem 2: for problem 2, add the sleep function and wait a few milliseconds for the loop to execute while the loop requests the lock
For problem 3: The key stored in the lock is random. In this case, every time you delete a key, check whether the value in the saved key is the same as that in your own key
$timeout = 10;
$roomid = 10001;
$key = 'room_lock';
$value = 'room_'.$roomid; // Assign a random value to problem 3
$isLock = Redis::set($key.$value, 'ex', $timeout, 'nx');/ / the ex seconds
if ($isLock) {
if (Redis::get($key) = =$value) { // Prevent locks created by other requests from being deleted
// Execute internal code
Redis::del($key);
continue;// Delete key successfully and exit the loop}}else {
usleep(5000); // Sleep, reduce snatch lock frequency, relieve redis pressure, for question 2}}while(!$isLock);
Copy the code
The above content hopes to help you, more free PHP factory PDF, PHP advanced architecture video materials, PHP wonderful good article can be wechat search concerns: PHP open source community
2021 Jinsanyin four big factory interview real questions collection, must see!
Four years of PHP technical articles collation collection – PHP framework
A collection of four years’ worth of PHP technical articles – Microservices Architecture
Distributed Architecture is a four-year collection of PHP technical articles
Four years of PHP technical essays – High Concurrency scenarios
Four years of elite PHP technical article collation collection – database