Implementation of redis distributed lock

The information found on the Internet for the implementation of distributed locks by redis is either a complicated implementation method (necessary when the redis version is relatively old), or there is a pit when releasing the lock, so I implemented one myself.
Support redis 2.6.12 and above.
It is also an implementation recommended by the redis official website. You can go to http://redis.io/commands/set to see the official website.

package com.extracme.evcard.redis;

import java.util.UUID;

import redis.clients.jedis.Jedis;

/**
 *
 * Redis does the implementation of distributed locks
 *
 * @author wu yibo
 */
public class JedisLock {

    private static final int ONE_SECOND = 1000;

    public static final int DEFAULT_EXPIRY_TIME_MILLIS = 5 * ONE_SECOND;

    private final Jedis jedis;

    private final String lockKey;
    private final int lockExpiryInMillis;
    private final UUID lockUUID;
    private boolean isLocked = false;

    
    /**
     * Generate lock object
     * @param jedis
     * @param lockKey
     */
    public JedisLock(Jedis jedis, String lockKey) {
        this(jedis, lockKey, DEFAULT_EXPIRY_TIME_MILLIS);
    }

    /**
     * Generate lock object
     * @param jedis
     * @param lockKey
     * @param expiryTimeMillis
     */
    public JedisLock(Jedis jedis, String lockKey, int expiryTimeMillis) {
        this(jedis, lockKey, expiryTimeMillis, UUID.randomUUID());
    }

    /**
     * Generate lock object
     * @param jedis
     * @param lockKey
     * @param expiryTimeMillis
     * @param uuid
     */
    public JedisLock(Jedis jedis, String lockKey, int expiryTimeMillis, UUID uuid) {
        this.jedis = jedis;
        this.lockKey = lockKey;
        this.lockExpiryInMillis = expiryTimeMillis;
        this.lockUUID = uuid;;
    }
    
    
    public UUID getLockUUID() {
        return lockUUID;
    }

    
    public String getLockKey() {
        return lockKey;
    }

    /**
     * lock
     * @return
     *
     * @author wu yibo
     */
    public synchronized boolean acquire() {
        return acquire(jedis);
    }

    /**
     * Locked.
     * Here is the use of redis set command to achieve locking, please see: http://redis.io/commands/set for details
     * @param jedis
     * @return
     *
     * @author wu yibo
     */
    protected synchronized boolean acquire(Jedis jedis) {
    	//nx表示:Only set the key if it does not already exist.
    	//ps means: Set the specified expire time, in milliseconds. The unit of timeout is milliseconds
    	if(!isLocked) {
    		isLocked = jedis.set(this.lockKey, this.lockUUID.toString(), "nx", "px", this.lockExpiryInMillis) != null;
    		return isLocked;
    	}
    	return false;
    }

    /**
     * release lock
     *
     * @author wu yibo
     */
    public synchronized void release() {
        release(jedis);
    }

    /**
     * release lock
     * @param jedis
     *
     * @author wu yibo
     */
    protected synchronized void release(Jedis jedis) {
    	if(this.isLocked) {
    		//Use the eval command to execute the Lua script
    		//If the value corresponding to the key in redis has changed, the delete instruction is no longer executed. Prevent the thread execution time from being too long by accident, causing the locks of other threads to be released when the lock is released
    		jedis.eval("if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end", 1, this.lockKey, this.lockUUID.toString());
    	}
    	isLocked = false;
    }

    /**
     * Check if locked
     * @return
     *
     * @author wu yibo
     */
    public synchronized boolean isLocked() {
        return this.isLocked;
    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326167311&siteId=291194637