Redis distributed locks with different opinions This article gives you a detailed explanation

Recommended reading: 350 Java interview questions: JVM + TCP + multithreading + distributed + algorithm + message queue

The text-straightforward

When it comes to redis locks, the following three are the most frequently used high-frequency words:

  • setnx
  • redLock
  • redisson

setnx

In fact, the setnx command currently commonly referred to is not a redis setnx key valuecommand.

General on behalf of that redis the set command with nx parameters to use, set this command now supports so many optional parameters:

SET key value [EX seconds|PX milliseconds] [NX|XX] [KEEPTTL]

Of course, I will not write Api in the article. The basic parameters are still unclear. You can jump to the official website .

 

 

The above picture is the general principle of setnx drawn by the author . It mainly relies on the feature that its key does not exist to set successfully . Process A gets the lock. When the key of the lock is not deleted, process B naturally fails to acquire the lock.

So why use it PX 30000to set a timeout?

I'm afraid that process A is unreasonable, and the lock hasn't waited to be released. In the event of a crash , the lock is taken away directly, causing no one in the system to get the lock.

 

 

Even so, there is no guarantee of foolproofness.

If process A is unreasonable and the resources in the operation lock exceed the timeout period set by the author , it will cause other processes to get the lock . When process A comes back, the lock of other processes is deleted, as shown in the figure:

 

Still the same picture just now, changed T5 time to lock timeout and was released by redis.

 

Process B happily got the lock at T6 for less than a while, process A completed the operation, and returned a del to release the lock.

When the process B operation is completed and the lock is released (time T8 in the figure):

 

 

It's actually good to find the lock. If a process C comes over to lock successfully at T7 , then process B will release the lock of process C. And so on, process C may release process D lock, process D .... (prohibition of nesting dolls), is not known what specific consequences.

Therefore, when using setnx , the key is the main function, but the value can not be idle, you can set a unique client ID , or use a random number such as UUID .

When unlocking, first obtain the value to determine whether it is a lock added by the current process, and then delete it. Pseudo code :

String uuid = xxxx;
// 伪代码,具体实现看项目中用的连接工具
// 有的提供的方法名为set 有的叫setIfAbsent
set Test uuid NX PX 3000
try{
// biz handle....
} finally {
    // unlock
    if(uuid.equals(redisTool.get('Test')){
        redisTool.del('Test');
    }
}
复制代码

Does this time seem stable?

On the contrary, the problem this time is more obvious. In the finally code block, get and del are not atomic operations , and there are still process security issues.

 

 

Why are there so many questions?

First, only by clarifying the disadvantages can we better improve them.

The second point, in fact, the last piece of code above is still used by many companies .

Paradox of large and small projects: Large companies implement specifications, but small companies and small projects are not rigorous, but their concurrency is not high. The probability of problems is as low as that of large companies. -Lu Xun

Then one of the correct postures to delete the lock is that you can use the lua script to run through the redis eval / evalsha command:

-- lua删除锁:
-- KEYS和ARGV分别是以集合方式传入的参数,对应上文的Test和uuid。
-- 如果对应的value等于传入的uuid。
if redis.call('get', KEYS[1]) == ARGV[1] 
    then 
	-- 执行删除操作
        return redis.call('del', KEYS[1]) 
    else 
	-- 不成功,返回0
        return 0 
end
复制代码

By lua script can guarantee atomicity reason to say it plainly:

Even if you write flowers in lua , the execution is also a command ( eval / evalsha ) to execute, a command is not completed, other clients can not see it.

So since it is so troublesome, are there any better tools? It's about redisson .


Before introducing redisson , I briefly explain why the current setnx refers to the set command with nx parameters by default , rather than directly saying the setnx command.

Because the redis version is before 2.6.12 , set does not support the nx parameter. If you want to complete a lock, you need two commands:

1. setnx Test uuid
2. expire Test 30
复制代码

That is, putting the key and setting the validity period are two separate steps. In theory, there will be 1 just after execution, the program hangs, and atomicity cannot be guaranteed.

However, as early as 2013 , that is, 7 years ago, Redis released version 2.6.12 , and the official website ( set command page ) also early stated that "SETNX, SETEX, PSETEX may be deprecated in future versions. And permanently delete ".

The author has read an article by a gangster, and there is a small interview guide for the beginner. The specific text is forgotten, and the general meaning is as follows:

When it comes to redis locks, you can start with setnx, and finally lead to the set command can add parameters, which can reflect your own knowledge.

If you have read this article before, and learned this routine, as the author of this article, I would like to add a reminder:

Please pay attention to your working years! First answer the order that the official website indicates that it is about to be scrapped, and then introduce the "new feature" of the set command seven years ago. If someone who has just graduated say so, the interviewer will think that he has crossed.

You set the road tester, the interviewer will also set you up. -vt Wozkisod

redisson

Redisson is one of java's redis clients , and provides some APIs for easy operation of redis.

But redisson this client can be a bit powerful, the author cut off only a part of the picture on the official website:

 

 

The list of features can be said to be too much, is not it also saw some JUC class package name below, redisson help us engage in a distributed version, such as AtomicLong , directly RedissonAtomicLong on the line, even the name of the class do not take up a new record , Very user-friendly.

The lock is just the tip of its iceberg, and from its wiki page, it supports master-slave, sentinel, and cluster modes. Of course, the single-node mode is definitely supported.

This article still focuses on locks, but not much else.

Redisson's ordinary lock implementation source code is mainly RedissonLock , and friends who have not seen its source code, may wish to take a look.

The lock / release lock operations in the source code are all done with lua scripts, the package is very perfect, and it works out of the box.

There is a small detail here. Locking can be achieved using setnx . Isn't it superfluous to use lua scripts? The author also thought very rigorously : how can such a powerful thing write waste code?

In fact, the author took a closer look. The lua script that locks and unlocks is considered very comprehensively, including the reentrancy of the lock . This can be said to be very thoughtful. I also wrote the code to test it:

 

 

It's really smooth like jdk's ReentrantLock , so redisson has been so perfect, what is redLock?

RedLock

redLock the Chinese are literal translation, called red locks .

Red lock is not a tool, but a distributed lock algorithm proposed by redis official .

In the redisson just introduced, the redLock version of the lock is implemented. In other words, in addition to the getLock method, there is also the getRedLock method.

The author probably drew an understanding of the red lock:

 

 

If you are not familiar with redis high availability deployment, then it does not matter. Although the redLock algorithm requires multiple instances, these instances are deployed independently and have no master-slave relationship.

The RedLock author pointed out that the reason for using the independent one is to avoid the lock loss caused by redis asynchronous replication, such as: the master node has not come and the data that has just been set in to the slave node is hung.

Do some people think that the bigwigs are all good, and think of extreme situations every day. In fact, high availability , the spelling is 99.999 ...% digits after the decimal point.

Returning to the simple picture above, the red lock algorithm believes that as long as 2N + 1 nodes are successfully locked, then it is considered that the lock has been acquired and all instances are unlocked when unlocked. The process is:

  1. Request locks from five nodes in sequence
  2. According to a certain timeout time to infer whether to skip the node
  3. The three nodes are successfully locked and take less time than the validity period of the lock
  4. Determined that the lock was successful

That is to say, assuming that the lock expires in 30 seconds , and it took 31 seconds for the three nodes to lock, naturally the lock fails.

This is just an example, each node in fact should not be so long, etc., as stated official network, it is assumed valid for 10 seconds , then redis example operation of a single timeout, it should be 5 to 50 ms (note time unit)

Or suppose we set the validity period to 30 seconds, and two redis nodes time out in the figure.
Then the node that successfully locked the lock took a total of 3 seconds, so the actual validity of the lock is less than 27 seconds.

That is, the 3 seconds of the three successful lock instances are deducted, and the total time waiting for the timeout redis instance is also deducted.

Seeing this, you may have some questions about this algorithm, then you are not alone.

Take a look back at the Redis website's description of the red lock

At the bottom of this description page, you can see the famous fairy fights about the red lock .

That is, Martin Kleppmann and antirez's redLock debate. One is a highly qualified distributed architect, and the other is the father of redis.

Official hang people, the most deadly.

To make a joke, if it is doubted that it can be hung on the official website, it must be valuable.

So if you want to use red locks in the project, in addition to the introduction of red locks, you may wish to read two more articles, namely:

  1. Martin Kleppmann's questioning post
  2. antirez's counterattack

to sum up

After reading so much, did you find out how to achieve it? You can't guarantee 100 % stability.

The procedure is like this, there is no absolute stability, so it is also an important part of doing manual compensation , after all:

Technology is not enough, come together manually ~


 
Published 238 original articles · Like 68 · Visits 30,000+

Guess you like

Origin blog.csdn.net/qq_45401061/article/details/104699529