You should only lock Redis

Speaking of Redis locks, the following three are considered to be the most frequent words:

  • Setnx
  • RedLock
  • Redisson

 

Setnx

 

The Setnx command commonly referred to at present does not only refer to the Redis setnx key value command.

 

Generally refers to the use of the Set command plus the NX parameter in Redis. The Set command currently supports so many optional parameters:

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

 

Of course, I will not write the API silently in the article. The basic parameters are still unclear, so you can jump to the official website.

The above figure 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 obtains the lock. When the key of the lock is not deleted, process B naturally fails to acquire the lock.

 

So why use PX 30000 to set a timeout period? I'm afraid that the process A is unreasonable, and the lock hasn't been released. If it collapses, the lock will be taken away directly, causing no one in the system to get the lock.

Even so, there is still no guarantee of foolproofness. If process A is unreasonable and the resources in the operation lock exceed the timeout period set by the author, then other processes will get the lock. When Process A comes back, the answer is to delete the locks of other processes, as shown in the figure:

In the picture just now, the T5 time is changed to the lock timeout, which is released by Redis.

 

Process B happily gets the lock at T6 and it takes less than a while. Process A finishes the operation and returns a Del to release the lock.

 

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

 

In fact, it is not bad that the lock cannot be found. If a process C comes to successfully lock at T7, then process B releases the lock of process C.

 

By analogy, process C may release the lock of process D, process D.... (Dolls are prohibited), the specific consequences are unknown.

 

So when using Setnx, although Key is the main function, Value cannot be idle. You can set a unique client ID or use a random number like UUID.

 

When unlocking, first obtain Value to determine whether it is a lock added by the current process, and then delete it. Fake 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 it look stable this time? On the contrary, this time the problem 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? There are two reasons:

  • Only by clarifying the disadvantages can we improve it better.
  • The last piece of code above is still used by many companies.

 

Paradox of large and small items:

Large companies implement standards, but although small companies and small projects are not rigorous, concurrency is not high, and the probability of problems is as low as that of large companies.

 

 

 

Then one of the correct postures to remove the lock is to use Lua scripts to run through Redis's eval/evalsha commands:

-- 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

 

The reason for ensuring atomicity through Lua scripts is a bit more popular: even if you write flowers in Lua, the execution is executed by a command (eval/evalsha). If a command is not executed, other clients cannot see it. .

 

So since it is so troublesome, is there a better tool? Let's talk about Redisson.

 

Before introducing Redisson, the author briefly explains why the current Setnx default refers to the Set command with NX parameters, instead of directly referring to the Setnx command.

 

Because the Redis version is before 2.6.12, Set does not support NX parameters. If you want to complete a lock, you need two commands:

1. setnx Test uuid
2. expire Test 30

 

That is, putting in 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.

 

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

 

The author once read an article by a big guy. Among them, there is a small interview routine that guides beginners. The specific text is forgotten. It probably means the following: When it comes to Redis locks, you can start with Setnx first, and then slowly elicit it. You can add parameters to the Set command to reflect your own knowledge.

 

If you have read this article by fate, 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 command that the official website indicates that it is about to be discarded, and then introduce the "new features" of the Set command seven years ago. If someone who has just graduated says this, the interviewer will think that he has gone through.

You do the interviewer, the interviewer will also do you.  


- vt·Wozkistock

 

Redisson

 

Redisson is one of Java's Redis clients and provides some APIs to facilitate the operation of Redis.

 

But the Redisson client is a bit powerful. The author has cut only a part of the picture on the official website:

This feature list can be said to be too much. Have you seen some of the class names under the JUC package? Redisson helped us make a distributed version.

 

For example, AtomicLong, just use RedissonAtomicLong directly, you don't even need to remember the class name, which is very user-friendly.

 

Locking is only the tip of its iceberg, and from its Wiki page, it supports master-slave, sentinel, cluster and other modes. Of course, single-node mode is definitely supported.

 

This article is still focused on locks, and the others will not be introduced. Redisson's common lock implementation source code is mainly RedissonLock. Those 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 complete, and it works out of the box.

Here is a small detail. Locking can be achieved using Setnx. Is it unnecessary to use Lua scripts?

 

The author also thought about it very rigorously: How can such a powerful thing write waste code?

 

In fact, the author took a closer look. The Lua script for locking and unlocking is very comprehensive, including the reentrancy of the lock. This can be said to be very thoughtful. I also wrote the code to test it:

It is indeed as silky as JDK's ReentrantLock, so Redisson has been implemented so well, what is RedLock?

 

RedLock

 

 

The Chinese of RedLock is literally translated, and it is called RedLock. Red lock is not a tool, but a distributed lock algorithm officially proposed by Redis.

 

In Redisson, which was just introduced, the RedLock version of the lock was implemented. In other words, in addition to the getLock method, there is also the getRedLock method.

 

The author probably drew the understanding of the red lock:

If you are not familiar with Redis high-availability deployment, then it doesn't matter. Although the RedLock algorithm requires multiple instances, these instances are deployed independently, and there is no master-slave relationship.

 

The author of RedLock pointed out that the reason for using independent is to avoid lock loss caused by Redis asynchronous replication. For example, if the master node does not come and the data just set in to the slave node, it hangs.

 

Do some people think that big guys are good at levers, thinking about extreme situations every day. In fact, it's highly available, it's 99.999...% of the digits after the decimal point.

 

Going back to the simple picture above, the red lock algorithm believes that as long as 2N+1 nodes are successfully locked, then the lock is considered to be acquired, and all instances are unlocked when unlocking.

 

The process is:

  • Request locks from five nodes in sequence
  • Infer whether to skip the node based on a certain timeout period
  • The three nodes are successfully locked and the time spent is less than the validity period of the lock
  • Confirm that the lock is successful

 

In other words, assuming that the lock expires in 30 seconds, and it took 31 seconds to lock the three nodes, it is natural that the lock failed.

 

This is just an example. In fact, you shouldn’t wait that long for each node. As the official website says, assuming the validity period is 10 seconds, the timeout period for a single Redis instance operation should be between 5 and 50 milliseconds (note the time unit).

 

Suppose we set the validity period to 30 seconds, and two Redis nodes have timed out in the figure. Then the node that successfully locked the lock took 3 seconds in total, so the actual validity period of the lock is less than 27 seconds.

 

That is, the 3 seconds for successfully locking the three instances is deducted, and the total time of waiting for the timeout Redis instance is also deducted. Seeing this, you may have some questions about this algorithm, then you are not alone.

 

Look back at the description of Red Lock on the Redis official website. At the bottom of this description page, you can see the famous fairy fight about Red Lock.

The RedLock debate between Martin Kleppmann and Antirez. One is a highly qualified distributed architect, and the other is the father of Redis.

 

Officially linked people are the most deadly. Just kidding, if the question can be listed on the official website, it must be valuable.

 

So if you want to use Red Lock in your project, in addition to the introduction of Red Lock, you might as well read two more articles, namely:

  • Questioning post by Martin Kleppmann

  • Antirez's counterattack post

Guess you like

Origin blog.csdn.net/baidu_39322753/article/details/104943302