Implementation of Redis lock for distributed scheduled tasks

Source: Internet
Author: User

A Web project if deployed as distributed, the usual timer service There may be multiple repeated calls within a certain interval of time。 At this point, because of the competition between the different containers, the container-level lock Redis is a single-process single-threaded mode with queue mode to make the concurrent access into serial access. Redis itself does not have the concept of locking, and Redis has no competition for multiple client connections. However, the lock can be implemented by SETNX.


setnx Command (SET if not exists)

Grammar:
Setnx Key value
Function:
Set the value of key to value if and only if key does not exist, and if the given key already exists, SETNX does nothing.

Complexity of Time:
O (1)
return value:
Set success, return 1.
Setting failed, returns 0.

Mode: Setnx with locked (locking)

Setnx can be used as Ka Yuan (locking primitive). For example, to lock the keyword (key) foo, the client can try the following:

Setnx Lock.foo <current Unix time + lock timeout + 1>

If Setnx returns 1, the client has acquired a lock, and the Unix time set by key specifies when the lock is invalidated. The client can then release the lock via DEL Lock.foo.

If Setnx returns 0, the key is already locked by another client. If the lock is non-blocking (non blocking lock), we can choose to return the call, or enter a retry loop until the lock is successfully obtained or the retry timeout (timeout).

However, it has been proved that only using SETNX lock with competitive conditions can cause errors in certain situations.

Handling Deadlocks (Deadlock)

The lock algorithm above has a problem: what if there is no way to release the lock because of a client failure, crash, or other cause?

This condition can be detected by detection-because the locked key holds the Unix timestamp, if the timestamp of the key value is less than the current timestamp, the lock is no longer valid.

However, when more than one client detects that a lock is out of date and tries to release it, we cannot simply and rudely delete the deadlock key, and then lock it with SETNX because the race condition (race condition) has been formed:

C1 and C2 read the Lock.foo and check the timestamp, SETNX returns 0 because it has been locked by the C3, but C3 crashes (crashed) after it is locked.
C1 sends the DEL command to Lock.foo.
C1 sends Setnx to Lock.foo and succeeds.
C2 sends the DEL command to Lock.foo.
C2 sends Setnx to Lock.foo and succeeds.
Error: Because of the competitive conditions of the relationship, C1 and C2 two have acquired the lock.



Fortunately, the following algorithms can avoid these problems. Let's see what our smart C4 clients do:

C4 sends the SETNX command to Lock.foo.
Because the collapsed C3 still locks the Lock.foo, Redis returns 0 to C4.
C4 send the GET command to Lock.foo to see if the Lock.foo lock is out of date. If not, hibernate (sleep) for a period of time and retry later.
On the other hand, if the Unix timestamp in Lock.foo is older than the current timestamp, C4 executes the following command:
Getset Lock.foo <current Unix timestamp + lock timeout + 1>


Because of the role of Getset, C4 can check the return value of Getset, determine whether the old value stored before Lock.foo is still the expiration timestamp, and if so, C4 get the lock.
If other clients, such as C5, perform getset operations more quickly than C4 and acquire locks, then C4 's getset operation returns an unexpired timestamp (the timestamp of the C5 setting). C4 had to retry from the first step.
Note that even if C4 's getset operation changes the key, it has no effect on the future.

This assumes that the value of the lock key does not have actual business meaning, otherwise there will be a problem, and in fact its value should not be used in the business.

To make the lock algorithm more robust, the client that gets the lock should often check the expiration time to prevent the lock from being accidentally unlocked because of a command such as DEL, because the client fails in such a complex way that it is not just a crash, it may be that the client has been blocked for quite a long time, and then the DEL The command was attempted (but at this point the lock was in the hands of another client).


getset Command
Syntax: Getset key value

Function:
Sets the value of the given key to value and returns the old value of the key. An error is returned when key exists but is not a string type.

Complexity of Time:
O (1)

return value:
Returns the old value of the given key, or nil if key does not exist when it does not have an old value.
Ref by
Http://blog.csdn.net/hpb21/article/details/7893013http://redis.readthedocs.org/en/latest/string/setnx.html It can be seen that if you want to implement distributed scheduled tasks, you only need to let multiple servers compete for Redis locks

Implementation of Redis lock for distributed scheduled tasks

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.