Distributed Lock --redis (single node)

What is the distributed lock

When learning Java multi-threaded programming, the lock is a very important and very basic concept, the lock can be seen as a thread synchronization mechanisms to access shared resources of multiple threads. This is for a single-process applications, namely when all threads in the same process in the JVM, use the Java language provides locking mechanism for shared resources can play the role of synchronization. If multiple different threads need to synchronize distributed environment of shared resources, then use Java's locking mechanism can not be achieved, and this time you have to rely on a distributed lock to solve the synchronization problem shared resources in a distributed environment. Distributed Lock There are many solutions, today we talk about is how to use caching database Redis to implement a distributed lock.

Redis a distributed lock program

Use Redis implement distributed lock the simplest solution is before acquiring the lock to check what with the lock for the key corresponding value exists or not, if there is, it indicates that the lock is other clients acquired, otherwise it will try to acquire a lock acquiring a lock method is very simple, as long as the lock key, a random value is provided on the line. For example, we have a number of tasks required by multiple distributed processing threads, each task has a taskId, in order to ensure that each task is executed only once, before the worker to perform tasks to get the job lock, lock key can taskId. Thus, the process of acquiring the lock can be implemented using the following pseudocode:

img

Above is the simplest solution to acquire the lock, but we can think of this scheme has the problem? Is there any potential pit? Before analyzing the advantages and disadvantages of this approach, first talk about after acquiring a lock is how we generally use the lock, and is how to release the lock, the Java language as an example, we generally get the lock will release the lock code on finally block, the benefits of doing so even if there is a lock in the process of abnormal use, the lock can be smoothly released. Pseudocode described as follows:

img

Wherein the method pseudocode getLock been given above, RELEASELOCK method is a method to release the lock, in this embodiment, simply delete key, not a given pseudo-code.

Use the above code lock at first glance is no problem, learned Java people know, in ... try ... finally block of code, even if the try block throws an exception, finally will eventually execute the code block, however, so it can guarantee the lock will be released it? Consider a case where: code execution to the doSomething () method, the server is down, this time finally block would not be able to be performed, so in this case, the lock is not properly released, the above cases, could lead to task omission. Therefore, the first problem with this approach is that there will be the risk of lock can not be released properly, the solution to this problem is very simple, Redis set key when you can specify an expiration date, as long as acquiring the lock set a reasonable time expired time, even if the server is down, but also to ensure the lock is released properly.

Another problem with this approach is that the lock is not necessarily to get an exclusive lock, that is to say the same lock at the same time might be to get a different client. Careful analysis getLock method is not atomic, when a client checks to a lock does not exist, and before performing the setKey method, other clients may also check into the lock does not exist, and will setKey execution method, this way, the same lock is likely to be different to the client obtains.

Since this program has more than disadvantages, then how to improve it? Listen to me slowly come.

Redis Distributed Lock Option II

On a section of the program has two disadvantages, it is to obtain a lock may not be released, and the other is the same lock may be acquired at the same time in different threads. By looking at Redis document, you can find Redis provides a key will only be set in the case of a key value that does not exist atomic command, the command can set key values ​​expiration time, so use this command, the above solution does not exist emerging issues, the command is:

SET my_key my_value NX PX milliseconds

Which, NX said that only when there is no key key will set the value of the key, PX represents a key set of key expiration time, in milliseconds.

Thus, the process of acquiring the lock may be described in the following pseudocode:

img

Wherein, setKeyOnlyIfNotExists method represents the atomic command SET my_key my_value NX PX milliseconds.

Thus, to obtain a lock code should be no problem, but the program will still be other problems. We carefully studied the released lock code. Because now we set the key, it also sets an expiration time, so the original release of the lock code now appears to have a problem. Consider a case where: client A to obtain the lock when the key is provided expiration time of 2 seconds, then client A after obtaining the lock, the business logic method doSomething performed 3 seconds (greater than 2 seconds), when executing the when the business logic method, the client a lock has been acquired Redis expired automatic release mechanism, so the client a after two seconds elapse acquiring the lock, the lock may have been acquired to other clients. When the client A method doSomething been executed next step is to perform releaseLock method releases the lock, because said earlier, the locks may have been acquired to other clients, so this time it is possible to release the lock is released by another client gets to lock.

Redis Distributed Lock Option Three

Since the program two problems may occur release the lock of another client application, then how to improve it? There is a very simple way that we set key when the value is set to a random value r, when the lock is released, that is, when the delete key, not directly deleted, but first determine whether the key corresponding to the value equal to the previous random value only when the two are equal when it deleted the key, since each random value generated by the client is not the same, such an action would not be wrong to release the lock of the other client applications. The new release the lock solution described below in pseudocode:

img

Which, getKey method is to query the Redis key value, deleteKey method is to delete the key value of the Redis, this does not give pseudo code.

Then this program is no problem? I regret to say that this program is also problematic. The reason is that the above-mentioned lock release operation is not atomic and atomic operations are not means that when a client getKey been performed and before performing the method deleteKey method, i.e. the method is performed between the two, the client can perform other other commands. Consider a case where, after executing the method getKey client A, and the key corresponding to the previous value is also equal to the random value, the client A will be executed next deleteKey method. Assuming that due to network or other reasons, Client A over 1 seconds to execute deleteKey method after the execution getKey method, then this one second in the key may also have been due to expire Redis cleared, so that the other a client, let's call the client B, it is possible to get to lock in this period, then the next client a to deleteKey on the implementation of the method, and this way it appeared mistakenly released another client application locks problem.

Redis Distributed Lock Option IV

Since the program three issue because the lock release method is not atomic lead, then we just make sure to release the lock code are atomic able to solve the problem. Regrettably, access Redis development documents, and found no atomic operations. Fortunately, the implementation of atomic operations in more than Redis command has provided official way, there is another way, that is, Lua script. Therefore, the release of three locks in program code can be used to achieve the following Lua script:

img

Wherein ARGV [1] represents a random value specified when setting key.

Because atomic Lua scripts, Redis during execution of the script, the other client orders need to wait for the Lua script completes to perform, Option III said the problem does not arise. So far, the use of distributed lock Redis achieve the program is relatively improved.

to sum up

Distributed Lock realization of the above, the terms are for single-node Redis, but in a production environment, we usually use Redis cluster, and each will have primary node from the node. Since Redis master-slave replication is asynchronous, so the above solution at ambient Redis cluster is also problematic. On how to gracefully implement distributed lock in Redis cluster, subsequent write detailed articles.

Guess you like

Origin www.cnblogs.com/snail-gao/p/11767316.html