Redis实现分布式锁机制

Redis实现分布式锁思路
  常用的是redis函数是setnx(),这个应该是实现分布式锁最主要的函数。首先是将某一业务标识名作为键存到redis里,并为其设个过期时间,如果是还有加锁请求过来,先是通过setnx()看看是否能将锁的标识插入到redis里,可以的话就返回true,不可以就返回false。
  
  此处使用Lua脚本简单的实现Redis锁的实现 :

package com.tencent.sxwx.wechat.util;


import redis.clients.jedis.Jedis;

public class DistributeLocker {

    private Jedis jedis;

    private Lock lock;
	/**
	 * 加锁成功标识
	 */
    private static final String LOCK_SUCCESS = "1";
	/**
	 * 脚本入参个数
	 */
    private static final int KEY_COUNT = 1;
	/**
	 * 加锁脚本
	 */
    private static String LOCK_SCRIPT;
	/**
	 * 解锁脚本
	 */
    private static String RELEASE_SCRIPT;
	/**
	 * 初始化脚本
	 */
    static {
        LOCK_SCRIPT = "local key = redis.call('get',KEYS[1]) if ('1' == key) then return 0 "
                + "else redis.call('set',KEYS[1],'1') redis.call('expire',KEYS[1],ARGV[1]) return 1 end";
        RELEASE_SCRIPT = "if (redis.call('exists',KEYS[1])) then redis.call('del',KEYS[1]) end";
    }
    /**
	 * 定义带参构造函数
	 */
    public DistributeLocker (Lock lock) { }
    public void lock (final String key, final int exprieTime) {
        if (isLocked(key, exprieTime)) {
            lock.success();
        } else {
            lock.failure();
        }
    }
	/**
	 * 加锁逻辑
	 */
    private boolean isLocked(final String key, final int exprieTime) {
        Object obj = jedis.eval(LOCK_SCRIPT, KEY_COUNT, key, String.valueOf(exprieTime));
        if (LOCK_SUCCESS.equals(obj)) {
            return true;
        }
        return false;
    }
	/**
	 * 解锁逻辑
	 */
    public void releaseLock (String key) {
        jedis.eval(RELEASE_SCRIPT, KEY_COUNT, key);
    }
}


package com.tencent.sxwx.wechat.util;

public interface Lock {

    void success();

    void failure();
}
package com.tencent.sxwx.wechat.util;

public class Test {

    void purchase(String key, int secondTime){
        DistributeLocker locker = new DistributeLocker(new Lock() {
            @Override
            public void success() {
                // do something
            }

            @Override
            public void failure() {
                // do something
            }
        });
        try {
            locker.lock(key,secondTime);
        } finally {
            locker.releaseLock(key);
        }
    }
}

注:Redis分布式锁的实现方式有很多种,各有利弊,加锁的时候主要注意检查锁与加锁操作要有原子性,防止重复加锁成功。过期时间主要是为了防止未释放锁导致锁的一直存在,从而无法获取锁操作。

猜你喜欢

转载自blog.csdn.net/weixin_38422258/article/details/84196802