Redis分布式锁

一、实现分布式锁的方式

1. 数据库乐观锁

2. Redis分布式锁

3. zookeeper分布式锁

二、锁的条件

1. 互斥性

2. 不会发生死锁

3. 容错性

4. 加锁和解锁必须是同一个客户端

三、加锁

jedis.set(key,value,NX,PX,time) 保证原子性,value为请求id保证解锁的也是同一个客户端

public class RedisTool {

    private static final String LOCK_SUCCESS = "OK";
    private static final String SET_IF_NOT_EXIST = "NX";
    private static final String SET_WITH_EXPIRE_TIME = "PX";

    /**
     * 尝试获取分布式锁
     * @param jedis Redis客户端
     * @param lockKey 锁
     * @param requestId 请求标识
     * @param expireTime 超期时间
     * @return 是否获取成功
     */
    public static boolean tryGetDistributedLock(Jedis jedis, String lockKey, String requestId, int expireTime) {

        String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);

        if (LOCK_SUCCESS.equals(result)) {
            return true;
        }
        return false;

    }

}

四、解锁

jedis.eval(),使用Lua脚本,保证原子性,和解锁的是同一个客户端

public class RedisTool {

    private static final Long RELEASE_SUCCESS = 1L;

    /**
     * 释放分布式锁
     * @param jedis Redis客户端
     * @param lockKey 锁
     * @param requestId 请求标识
     * @return 是否释放成功
     */
    public static boolean releaseDistributedLock(Jedis jedis, String lockKey, String requestId) {

        String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));

        if (RELEASE_SUCCESS.equals(result)) {
            return true;
        }
        return false;

    }

}

参考:

https://www.cnblogs.com/linjiqin/p/8003838.html

原文地址:https://www.cnblogs.com/june0816/p/11388246.html