How to use Redis to implement distributed locks? The following article will introduce to you the method of implementing distributed locks based on Redis. I hope it will be helpful to you!
#In a distributed system, you will encounter situations where resources shared by multiple nodes need to be locked. In this case, distributed locks need to be used. Distributed locks are usually stored in a shared storage system and can be shared and accessed by multiple nodes. [Related recommendations: Redis video tutorial]
Simply speaking, a lock can be represented by a variable. For example, in a single-machine multi-threaded program, the lock of a certain resource can be represented by one bit of data. That is, 0 means that no resource can be accessed, and 1 means that the resource lock has been acquired by another thread and cannot be accessed.
Acquiring and releasing the lock of a specific resource is essentially to obtain and modify the value of this variable. If the value is 0, modify it to 1 to complete the acquisition process. If the value accessed is not 0, the acquisition of the lock fails; if the lock has been acquired before, the value of the variable representing the lock is modified to 0. In fact, it is the operation of releasing the lock.
In a distributed scenario, the way to implement locks is the same, except that the variable representing the resource lock needs to be stored in a shared storage system. This shared storage system can be Redis or any other system that can provide data storage.
For the case of using Redis as this shared storage system , the variable representing the lock of a certain resource is a key-value pair in Redis. If the resource that needs to be added with a distributed lock is called resource_a, we can call the key of the lock variable of resource_a in Redis lock_a.
For example, if node 1 needs to acquire a lock, it will access the value of lock_a in Redis. Assuming that the obtained value is 0, node 1 will complete the locking operation after setting this value to 1. At this time, node two also needs to obtain the lock of resource_a. It accesses the value of lock_a in Redis and finds that the value is 1, indicating that the lock has been acquired by another node and has not been released. Therefore, node two fails to lock resource resource_a. .
When node one needs to release the lock, it only needs to set the value of lock_a in Redis to 0 to complete the lock release. After that, other nodes can acquire the resource lock again.
In the above description, locking is not a single operation, but includes multiple steps: Read the lock variable, determine the value of the variable, and modify the lock variable. These three operations need to be atomic.
In Redis, there is a SETNX command, which is used to set the value of a key-value pair. Different from the SET command, it will determine whether the key-value pair exists in advance, and only when the specified KEY does not exist Only when the value is set will the value setting be executed, otherwise nothing will be executed. SETNX means "SET if Not eXist". Its usage is the same as SET:
SETNX lock_a 1
In this way, when you need to acquire a lock, use the SETNX command to set a value for lock_a. If the setting is successful, the lock is acquired. If it fails, the lock is not acquired; when needed When releasing the lock, use the DEL operation to delete the key-value pair.
This achieves the atomic operation of acquiring and releasing locks.
Next, consider a problem early. If after the node acquires the lock, due to program exceptions and other reasons, it will cause The lock has not been released. At this time, the lock will always be held by it and cannot be released, and other nodes cannot access the resource.
In order to avoid this situation from happening, we must set the expiration time for the lock variable. When the lock variable expires, we can re-request the lock, thus avoiding this problem.
The SETNX command does not have an option to set the expiration time. Fortunately, Redis provides the NX option to simulate SETNX for the SET command. We can set the expiration time like this:
SET lock_a 1 NX PX 10000
The above command represents , if lock_a does not exist, its value is set to 1 and expires after 10 seconds.
The last question is, if node one acquires the lock, and for some reason, node two executes DEL operation, then other nodes can acquire the lock again.
In order to solve this problem, we can modify the content saved in the lock variable. In the previous logic, when we apply for a lock, we determine whether the lock variable exists, and it has little to do with the value stored in it. Therefore, we can use this value.
When locking, if the value is saved as the unique identifier of each node, then the value is judged before releasing the lock and executing DEL. Then, you can first judge whether the lock is added to the current node. , if yes, then release it, thus realizing "whoever locks the lock releases it".
In this part, there is no single instruction that can complete the operations of reading the lock variable, judging, and deleting it. Therefore, it can be implemented using a Lua script. Obtain the value of the current lock variable in the script and compare it with the given node identifier. If it matches, the deletion operation will be performed. Otherwise, no operation will be performed.
When releasing the lock, just execute the Lua script.
After improving the functions, finally implement high availability. If we use a single Redis as a shared storage system for distributed locks, then if this Redis is unavailable, then all parts related to distributed locks will be unavailable. This is a very fragile lock, which is very effective for high availability. necessary reasons.
At this time, it is necessary to move out the distributed lock algorithm Redlock proposed by Antirez, the author of Redis. In short, the lock applicant is asked to request locks from multiple independent Redis instances. If the lock operation can be completed on more than half of the Redis instances, then the lock is successfully obtained, otherwise the acquisition fails.
In the operation of releasing the lock, it can be regarded as successful as long as the Lua script that successfully deletes the lock variable is executed on more than half of the instances.
For more programming-related knowledge, please visit: Introduction to Programming! !
The above is the detailed content of How does Redis implement distributed locks? Let's talk about implementation methods. For more information, please follow other related articles on the PHP Chinese website!