1. Simple lock
redis Of setnx
Commands can provide mutual exclusion , A simple distributed lock can be implemented
1.1 Lock
127.0.0.1:6379> SETNX lock 1(integer) 1 // client 1, Locking success
127.0.0.1:6379> SETNX lock 1(integer) 0 // client 2, Locking failed
1.2 Release the lock
del
The command can release the lock ,
127.0.0.1:6379> DEL lock // Release the lock (integer) 1
1.3 Existing problems
The deadlock problem : Thread hang up or program exception , Lock cannot be released
2. Simple lock + Overtime
setnx+expire You can add a timeout for distributed locks , In this way, the deadlock problem can be solved
2.1 Realization
127.0.0.1:6379> SETNX lock 1 // Lock (integer) 1127.0.0.1:6379> EXPIRE lock 10 // 10s Automatically expire after (integer) 1
2.2 problem
- Lock expired : Threads 1 When holding the lock , Due to the long execution time of the program , Cause lock to expire , At this time, if the lock is obtained by other threads , Prone to concurrency problems
- Release the locks of other threads : stay 1 Under the circumstances , When a thread 1 After executing the procedure , It is likely to release the lock of thread 2
3 Simple lock + Overtime + Threads id
3.1 Realization
When you lock it key To lock resources , value For threads id, Verify the thread when unlocking , It can ensure that the lock will not be released by other threads
// The lock VALUE Set to UUID127.0.0.1:6379> SET lock $uuid EX 20 NXOK
// The lock is your own , To release if redis.get("lock") == $uuid: redis.del("lock")
3.2 problem
- Non atomic operation when releasing lock , First get Again del, ( No big problem , In general, concurrent requests in programs are setnx, If you use set There will be problems )
- The problem of lock expiration still exists
3.3 Optimize
Use lua Script release lock can achieve atomization
// Judge that the lock is your own , To release if redis.call("GET",KEYS[1]) == ARGV[1]then return redis.call("DEL",KEYS[1])else return 0end
4. Lock expiration problem
in summary , Use setnx + Overtime + Threads id+lua Script It can basically realize a rigorous distributed lock
The only problem seems to be the lock timeout , The lock timeout problem can be handled as follows :
When locking , Set an expiration time first , And then we start a new one 「 The guardian thread 」, Check the failure time of the lock regularly , If the lock is about to expire , The operation of shared resources has not been completed , Then the lock is automatically locked 「 Renewal 」, Reset expiration time .
Mature solutions in the industry include redission, Can provide
- Reentrant lock
- Optimism lock
- Fair lock
- Read-write lock
- Redlock( Red lock , I'll talk about it in detail )
Please refer to
0. Project introduction - 《Redisson User manual 》 - Book stack net · BookStack