Redis implements distributed locks: He said that his distributed locks are very lucrative

Insert picture description here

What is a distributed lock?

In order to prevent mutual interference between multiple processes in a distributed system, we need a distributed coordination technology to schedule these processes. The core of this distributed coordination technology is to realize this distributed lock.

Understand the basic concepts through the implementation of Redis distributed locks

Three core elements of distributed lock implementation:

Locked:

The easiest way is to use the setnx command. The key is the unique identifier of the lock, and it is named according to the business. For example, if you want to lock the spike activity of a product, you can name the key "lock_sale_product ID". And what is the value set to? We can set it to 1 temporarily. The pseudo code for locking is as follows:

setnx(lock_sale_商品ID,1

When a thread executes setnx and returns 1, it means that the key does not originally exist and the thread successfully obtained the lock; when a thread executes setnx and returns 0, it means that the key already exists and the thread fails to grab the lock.

Unlock

If there is a lock, there must be an unlock. When the thread that gets the lock finishes 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 instruction, the pseudo code is as follows:

del(lock_sale_商品ID)

After the lock is released, other threads can continue to execute the setnx command to obtain the lock.

Lock timeout

What does lock timeout mean? If a thread that gets a lock hangs up during the execution of a task and it is too late to release the lock explicitly, this resource will be locked forever (deadlock), and other threads will never want to come in. Therefore, the key of setnx must be set with a timeout period to ensure that the lock will be automatically released after a certain period of time even if it is not explicitly released. setnx does not support timeout parameters, so additional instructions are needed. The pseudo code is as follows:

expire(lock_sale_商品ID, 30

Redis distributed lock implementation and analysis of various problems

SETNX

We can easily implement a redis distributed lock with the SETNX command.
What is SETNX? If you still don’t understand, let’s scavenge first:

Set the key to value. If the key does not exist, it is equivalent to the SET command in this case. When the key exists, do nothing. SETNX is short for "SET if Not
eXists".

return value:

   1 如果key被设置了
    0 如果key没有被设置

Original code

····
事务实现(比方说:扣除库存)
····

First lock


string key = "key";
string values = "values";

···

bool result = 调用SETNX(key,values);
if(!result)
	return;

事务操作

redis中销毁key

···

The result lock is added here. When a thread obtains this lock, the results of other threads are all 0 and blocked.


Second lock

The above lock has some bugs. Come and see one by one.

What happens if the card gets stuck during the transaction operation? Then this lock will not deadlock forever! ! !
What to do then?
Yes, try···finally···


string key = "key";
string values = "values";

try{
    
    
	bool result = 调用SETNX(key,values);
	if(!result)
		return;

	事务操作
}catch(){
    
    
	redis中销毁key
}
redis中销毁key

Third lock

Okay, the problem of throwing exceptions is solved. What if I directly hang up the entire thread now?
What to do then?
There is no way for this try.

Yes, set a timeout for this lock.
Don't forget, in the final analysis, this lock is a key.


string key = "key";
string values = "values";

try{
    
    
	bool result = 配置一个有时限的SETNX锁;	//在redis下有个操作,将SETNX和生命期配置两个原子操作合二为一
	if(!result)
		return;

	事务操作
}catch(){
    
    
	redis中销毁key
}
redis中销毁key

Well, to solve the general distributed lock, it is already OK here.

However, the man said that his distributed lock is very lucrative


The fourth lock

Have you ever thought that the lock above you is set for 10 seconds, if a task suddenly comes, it will be executed for 15 seconds. Then there is a problem.

线程A:拿到锁,执行15秒,在第10秒的时候,锁被redis给释放掉了。

线程B:锁已经被释放,拿锁,执行8秒,但是在执行到第五秒的时候,,,,锁被线程A给释放了哈哈哈哈哈哈

线程C:不说了,运气不好又被别的线程把他的锁给放了。。。。

In a high concurrency scenario, the progress of the background thread is simply uncontrollable! ! !

Isn't that finished? ? ?

What to do then?

For each value of the lock, configure the unique id of your own thread. When unlocking, check if it is your own lock. Don't unlock others'


string key = "key";
string values = 专属随机值;

try{
    
    
	bool result = 配置一个有时限的SETNX锁;	//在redis下有个操作,将SETNX和生命期配置两个原子操作合二为一
	if(!result)
		return;

	事务操作
}catch(){
    
    
	redis中销毁key
}
redis中,根据values,销毁key

Fifth lock

The fourth lock is actually very good, but there is still a problem left, right, that timeout lock is a problem after all.

What to do then? Set 60 seconds? Set 90 seconds?
What is the appropriate setting? It's not appropriate, it's blocked.

Renew.

As long as the lock is successful, open a sub-thread, add a timer to the sub-thread, and check whether the lock is still there every 10 seconds, and the thread is still not there, if it is still there, renew it to 30 seconds .

Actually, I don’t like this lock very much. If it really wants to be renewed like this, is the accumulation of the current locks all displayed?

You can think for yourself.


I'm here first today, and I made an appointment with my little sister for dinner at noon

Concluding remarks

It is recommended to collect it, because meeting is fate, you can't find it if you scratch it.

Insert picture description here

Guess you like

Origin blog.csdn.net/qq_43762191/article/details/108543510
Recommended