Redis-based SETNX (), Get (), Getset () Methods distributed locks

Source: Internet
Author: User
Tags current time redis set time


A. Redis command explanation:
SETNX () command:
The meaning of SETNX is the set if not Exists, which mainly has two parameters setnx (key, value).



The method is atomic if key does not exist, then the current key is set successfully, returns 1, and if the current key already exists, sets the current key to fail and returns 0.



Get () command:
Get (key) Gets the value of key, returns if it exists, or nil if it does not exist;
Getset () command:
This command consists of two parameters Getset (key, NewValue). The method is atomic, sets the value of NewValue to key, and returns the old value of the original key.
Assuming that the key originally does not exist, then execute this command more than once, the effect will appear below:
1. Getset (Key, "value1") returns nil at this point the value of key is set to value1
2. Getset (Key, "value2") returns value1 when the value of key is set to value2
3. In turn.
Two. The specific steps to use are as follows:
1. Setnx (Lockkey, current time + expiration timeout), if 1 is returned, the lock is obtained successfully, if return 0 does not acquire to lock, turn to 2.
2. Get (Lockkey) Gets the value Oldexpiretime and compares this value to the current system time, and if it is less than the current system time, it is considered that the lock has timed out, allowing other requests to be retrieved and turned 3.
3. Calculate newexpiretime= Current time + expiration timeout, then Getset (Lockkey, Newexpiretime) will return the current Lockkey value currentexpiretime.
4. Determine if Currentexpiretime is equal to oldexpiretime, if equal, indicates that the current Getset setting is successful and acquires the lock. If it is not equal, it means that the lock is taken away by another request, and the current request can either return directly to the failure or continue to retry.
5. After acquiring the lock, the current thread can start its own business processing, when it is finished, compare its processing time and the timeout for the lock setting, if it is less than the lock set time-out, the delete release lock is executed directly, and if the time-out is greater than the lock setting, no re-lock is required for processing.



The specific code is as follows:



Implement the distributed lock Distributedlockhandler class:



[Java] View plain copy
Package tk.mybatis.springboot.distributedLock;



Import Org.springframework.stereotype.Service;



Import Redis.clients.jedis.Jedis;



@Service ("Distributedlockhandler")
public class Distributedlockhandler {


private static final Integer Lock_Timeout = 3;

private Jedis jedis;

/ **
 * External call lock method
 * @param lockKey lock name
 * @param timeout timeout time (the length of time, such as 5L)
 * @return
 * /
public boolean tryLock (String lockKey, Long timeout) {
    try {
        Long currentTime = System.currentTimeMillis (); // Time to start locking
        boolean result = false;

        while (true) {
            if ((System.currentTimeMillis ()-currentTime) / 1000> timeout) {// The current time exceeds the set timeout
                System.out.println ("Execute DistributedLockHandler.tryLock method, Time out.");
                break;
            } else {
                result = innerTryLock (lockKey);
                if (result) {
                    break;
                } else {
                    System.out.println ("Try to get the Lock, and wait 100 millisecond ....");
                    Thread.sleep (100);
                }
            }
        }
        return result;
    } catch (Exception e) {
        System.out.println ("Failed to run DistributedLockHandler.getLock method." + E);
        return false;
    }
}

/ **
 * Release lock
 * @param lockKey lock name
 * /
public void realseLock (String lockKey) {
    if (! checkIfLockTimeout (System.currentTimeMillis (), lockKey)) {
        jedis.del (lockKey);
    }
}

/ **
 * Internal lock acquisition method
 * @param lockKey lock name
 * @return
 * /
private boolean innerTryLock (String lockKey) {

    long currentTime = System.currentTimeMillis (); // Current time
    String lockTimeDuration = String.valueOf (currentTime + Lock_Timeout + 1); // The duration of the lock
    Long result = jedis.setnx (lockKey, lockTimeDuration);

    if (result == 1) {
        return true;
    } else {
        if (checkIfLockTimeout (currentTime, lockKey)) {
            String preLockTimeDuration = jedis.getSet (lockKey, lockTimeDuration);
            if (currentTime> Long.valueOf (preLockTimeDuration)) {
                return true;
            }
        }
        return false;
    }

}

/ **
 * Determine if the lock has timed out
 * @param currentTime current time
 * @param lockKey lock name
 * @return
 * /
private boolean checkIfLockTimeout (Long currentTime, String lockKey) {
    if (currentTime> Long.valueOf (jedis.get (lockKey))) {// The current time exceeds the duration of the lock
        return true;
    } else {
        return false;
    }
}

public DistributedLockHandler setJedis (Jedis jedis) {
    this.jedis = jedis;
    return this;
} 


}



Call the Demo class:



[Java] View plain copy
Package tk.mybatis.springboot.distributedLock;



Import Redis.clients.jedis.Jedis;



/**
* Redis-based SETNX (), Get (), Getset () Methods distributed locks
* @author KF01
*
*/
public class Demo {
private static final String Lockkey = "Lock.tecentim_interface_counter";


public static void Main (string[] args) {  
    Jedis Jedis = new Jedis ("127.0.0.1", 6379);  

    Distributedlockhandler Distributedlockhandler = new Distributedlockhandler (). Setjedis (Jedis);  
    try{  
        Boolean getlock = Distributedlockhandler.trylock (Lockkey, long.valueof (5));  

        if (getlock) {  
            //do your job  
            System.out.println ("Do your Job ...");}  

    catch (Exception e) {  
        System.out.println (e);  
    } finally {  
        distributedlockhandler.realselock (lockkey);  
    }  

}  


}


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.