Comic: What is a distributed lock?

Comic: What is a distributed lock?

Click on the "Programmer Xiaohui" above, and select the "Top Official Account" to
deliver interesting and meaningful articles as soon as possible!
Comic: What is a distributed lock?
Comic: What is a distributed lock?

----- the next day-----

Comic: What is a distributed lock?
Comic: What is a distributed lock?
Comic: What is a distributed lock?
Comic: What is a distributed lock?
Comic: What is a distributed lock?
Comic: What is a distributed lock?

Comic: What is a distributed lock?
Comic: What is a distributed lock?
Comic: What is a distributed lock?
Comic: What is a distributed lock?
Comic: What is a distributed lock?

————————————
Comic: What is a distributed lock?

Comic: What is a distributed lock?

Comic: What is a distributed lock?
Comic: What is a distributed lock?
Comic: What is a distributed lock?

Comic: What is a distributed lock?

What are the implementations of distributed locks?

1. Memcached distributed lock

Use Memcached's add command. This command is an atomic operation. Only when the key does not exist can the add succeed, which means that the thread is locked.

2.Redis distributed lock

Similar to Memcached, using Redis' setnx command. This command is also an atomic operation, and the set can only be successful if the key does not exist. (The setnx command is not perfect, and alternatives will be introduced later)

3.Zookeeper distributed lock

Use Zookeeper's sequential temporary nodes to implement distributed locks and waiting queues. The original intention of Zookeeper design is to implement distributed lock services.

4.Chubby

The coarse-grained distributed lock service implemented by Google uses the Paxos consensus algorithm at the bottom layer.
Comic: What is a distributed lock?
Comic: What is a distributed lock?

How to use Redis to implement distributed locks?

The basic process of Redis distributed lock is not difficult to understand, but it is not so easy to write it perfectly. Here, we need to first understand the three core elements of distributed lock implementation:

1. Lock

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(key,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.

2. Unlock

If there is lock, there must be unlock. When the thread that got 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 (key)

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

3. Lock timeout

What does lock timeout mean? If a thread that gets the lock hangs up during the execution of the task, and it is too late to release the lock explicitly, this resource will be locked forever, 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 required. The pseudo code is as follows:

expire(key, 30)

Taken together, the first version of the pseudo code of our distributed lock implementation is as follows:

if(setnx(key,1) == 1){
expire(key,30)
try {
do something ......
} finally {
del(key)
}
}

Comic: What is a distributed lock?

Comic: What is a distributed lock?
Comic: What is a distributed lock?

Good code, why did you go home and wait for notification?

Because in the above pseudo code, there are three fatal problems:

  1. Non-atomicity of setnx and expire

Imagine an extreme scenario, when a thread executes setnx and successfully gets the lock:
Comic: What is a distributed lock?

Setnx has just been executed successfully, but there is no time to execute the expire command in the future, and node 1 Duang hangs up.
Comic: What is a distributed lock?

In this way, the lock does not have an expiration time set, and becomes "immortal", and other threads can no longer obtain the lock.

How to solve it? The setnx command itself does not support the incoming timeout period. Fortunately, Redis 2.6.12 and above have added optional parameters to the set command. The pseudo code is as follows:

set(key,1,30,NX)

This can replace the setnx instruction.

  1. del causes accidental deletion

Another extreme scenario, suppose a thread successfully gets the lock and the set timeout period is 30 seconds.
Comic: What is a distributed lock?

If for some reason the execution of thread A is very slow and slow, and the execution is not finished after 30 seconds, the lock will be automatically released when it expires and thread B will get the lock.
Comic: What is a distributed lock?

Subsequently, thread A finishes the task, and thread A then executes the del instruction to release the lock. But at this time thread B has not finished execution, thread A actually deletes the lock added by thread B.
Comic: What is a distributed lock?

How to avoid this situation? You can make a judgment before del releases the lock to verify whether the current lock is the lock you added.

As for the specific implementation, you can use the current thread ID as the value when locking, and verify that the value corresponding to the key is the ID of your own thread before deleting.

加锁:
String threadId = Thread.currentThread().getId()
set(key,threadId ,30,NX)

解锁:
if(threadId .equals(redisClient.get(key))){
del(key)
}

However, this implies a new problem. Judging and releasing the lock are two independent operations, not atomic.

We are all programmers pursuing the ultimate, so this part needs to be implemented with Lua scripts:

String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";

redisClient.eval(luaScript , Collections.singletonList(key), Collections.singletonList(threadId));

In this way, the verification and deletion process is an atomic operation.

3. The possibility of concurrency

The scene described in the second point just now, although we have avoided the situation that thread A deletes the key by mistake, it is still imperfect that two threads A and B are accessing the code block at the same time.

How to do it? We can let the thread that acquired the lock start a daemon thread, which is used to "life" the lock that is about to expire.
Comic: What is a distributed lock?

When 29 seconds have passed and thread A has not finished execution, the daemon thread will execute the expire instruction to "remain" the lock for 20 seconds. The daemon thread executes from the 29th second and executes every 20 seconds.
Comic: What is a distributed lock?

When thread A finishes executing tasks, it will explicitly shut down the daemon thread.
Comic: What is a distributed lock?

In another case, if node 1 suddenly loses power, the daemon thread will also stop because thread A and the daemon thread are in the same process. When the lock expires, no one will renew it, and it will be automatically released.
Comic: What is a distributed lock?

The code of the daemon thread is not difficult to implement. With a general idea, you can try to implement it yourself.
Comic: What is a distributed lock?
Comic: What is a distributed lock?

Comic: What is a distributed lock?

A few additions:

This comic is purely entertainment. Please cherish your current work as much as possible and do not imitate Xiao Hui's behavior.

—————END—————

Friends who like this article, please press and hold the picture to follow the subscription account programmer Xiaohui, and watch more exciting content

Comic: What is a distributed lock?

Guess you like

Origin blog.51cto.com/14982143/2550714