The article directories
-
- What is distributed locking?
-
- Understand the basic concepts through the Redis distributed lock implementation
-
- Lock:
- unlock
- The lock timeout
- Redis distributed lock implementation and various problems analysis
-
- SETNX
- The original code
- The first lock
- The second lock
- The third lock
- The fourth lock
- The fifth lock
- conclusion
What is distributed locking?
In order to prevent multiple processes from interfering with each other in a distributed system, we need a distributed coordination technique to schedule these processes. The core of this distributed coordination technology is to achieve this distributed lock.
Understand the basic concepts through the Redis distributed lock implementation
Three core elements of a distributed lock implementation:
Lock:
The simplest way is to use the setnx command. Key is the unique identifier of a lock and is named based on the service. For example, if you want to lock the kill activity of an item, you can name the key “lock_sale_ item ID”. And what is value set to? Let’s say we set it to 1. The pseudo-code for locking is as follows:
Setnx (lock_sale_ commodity ID,1)Copy the code
When a thread executes setnx and returns 1, the key does not exist and the thread successfully acquired the lock. When a thread executes setnx and returns 0, the key already exists and the thread fails to grab the lock.
unlock
Add lock must have unlock. When the thread that acquired the lock completes its task, it needs to release the lock so that other threads can enter. The simplest way to release the lock is to execute the del directive, with the following pseudocode:
Del (lock_sale_ commodity ID)Copy the code
After the lock is released, other threads can continue to execute the setnx command to acquire the lock.
The lock timeout
What do I mean by lock timeout? If a thread with a lock hangs in the middle of a task without explicitly releasing the lock, the resource is permanently locked (deadlocked) and no other thread can enter. Therefore, the setnx key must set a timeout period to ensure that the lock is automatically released after a certain amount of time, even if it is not explicitly released. Setnx does not support timeout parameters, so additional instructions are required, with the following pseudocode:
Expire (lock_sale_ commodity ID,30)Copy the code
Redis distributed lock implementation and various problems analysis
SETNX
We can use the SETNX command to easily implement a redis distributed lock. What is SETNX? If you still don’t understand, first scan the blind:
SET key to value. If key does not exist, this is equivalent to the SET command. While key exists, do nothing. SETNX is short for SET if Not eXists.
The return value:
1If the key is set0If the key is not setCopy the code
The original code
Transaction implementation (e.g., inventory deduction)Copy the code
The first lock
string key = "key";
string values = "values"; ...boolResult = callSETNX(key,values);
if(! result)return; The transaction operation Redis destroys the keyCopy the code
When one thread acquires the lock, all other threads’ results are zero and block.
The second lock
This lock up here, it has some bugs. Let’s take a look at them one by one.
What happens if something gets stuck during a transaction? Then this lock won’t be deadlocked forever!! So what? Yes, the try… finally…
string key = "key";
string values = "values";
try{
boolResult = callSETNX(key,values);
if(! result)return; Transaction operations}catch(){redis destroy key} redis destroy keyCopy the code
The third lock
Okay, so now that I’ve solved the exception throwing problem, what if I just hang the whole thread? So what? I’m not going to be able to do this try.
Yes, set a timeout for this lock. Remember, at the end of the day, this lock is a key.
string key = "key";
string values = "values";
try{
boolResult = configure a time-bound SETNX lock;// There is an operation under Redis that combines the SETNX and lifetime configuration atomic operations
if(! result)return; Transaction operations}catch(){redis destroy key} redis destroy keyCopy the code
OK, so general distributed locking is done here.
But, the man said, his distributed lock, very wet
The fourth lock
Did you ever wonder, that lock you have up there, it’s set for 10 seconds, and if a job comes along, it’s executed for 15 seconds. That’s a problem.
Thread A: Takes the lock and executes15Second, in the first10At seconds, the lock is released by Redis. Thread B: Lock has been released, take lock, execute8Second, but in the execution of the fifth second ,,,, lock was released by thread A hahahahahahaha thread C: not to say, bad luck was another thread to release his lock.Copy the code
In high concurrency scenarios, background thread progress is not controllable at all!!
That’s not the end??
So what?
Assign the values of each lock to its own thread id. When unlocking the lock, check to see if it is your own lock. Do not unlock others’ lock
string key = "key"; String values = exclusive random value;try{
boolResult = configure a time-bound SETNX lock;// There is an operation under Redis that combines the SETNX and lifetime configuration atomic operations
if(! result)return; Transaction operations}catch(){redis destroy key} redis destroy key according to valuesCopy the code
The fifth lock
The fourth lock was actually quite good, but there was still a problem, wasn’t there, with the timed lock? It was a problem after all.
So what? 60 seconds? 90 seconds? How much is appropriate? It doesn’t fit at all. There’s a blockage.
Renewed.
As long as the lock is successful, open a sub-thread, sub-thread add a timer, every 10 seconds to check that the lock is not in, the thread is not in, if it is still in, to renew it to 30 seconds.
This lock actually I don’t like very much, really want to renew like this, then the accumulation of the current several locks is decoration?
You can think about that for yourself.
Today is the first here, noon also about the little sister to eat
conclusion
Oh, because, meet is fate, scratching, can not find.