Skip to content
gqlxj1987's Blog
Go back

Redis Distribute Lock

Edit page

原文链接

分布式锁一般有如下的特点:

lua脚本的方式,放在一个事务中去

public boolean tryLock_with_lua(String key, String UniqueId, int seconds) {
    String lua_scripts = "if redis.call('setnx',KEYS[1],ARGV[1]) == 1 then" +
            "redis.call('expire',KEYS[1],ARGV[2]) return 1 else return 0 end";
    List<String> keys = new ArrayList<>();
    List<String> values = new ArrayList<>();
    keys.add(key);
    values.add(UniqueId);
    values.add(String.valueOf(seconds));
    Object result = jedis.eval(lua_scripts, keys, values);
    //判断是否成功
    return result.equals(1L);
}
SET key value[EX seconds][PX milliseconds][NX|XX]

EX seconds: 设定过期时间,单位为秒
PX milliseconds: 设定过期时间,单位为毫秒
NX: 仅当key不存在时设置值
XX: 仅当key存在时设置值

释放锁的情况,需要对value进行验证,仅释放自己设置的锁?

针对redis集群的方式,采用投票的机制来决定是否真正算获得了锁,也就是所谓的redLock算法

    public boolean tryLock(long waitTime, long leaseTime, TimeUnit unit) throws
            InterruptedException {
// 实现要点之允许加锁失败节点限制(N-(N/2+1))
        int failedLocksLimit = failedLocksLimit();
        List<RLock> acquiredLocks = new ArrayList<RLock>(locks.size());
// 实现要点之遍历所有节点通过EVAL命令执行lua加锁
        for (ListIterator<RLock> iterator = locks.listIterator(); iterator.hasNext(); ) {
            RLock lock = iterator.next();
            boolean lockAcquired;
            try {
// 对节点尝试加锁
                lockAcquired = lock.tryLock(awaitTime, newLeaseTime, TimeUnit.MILLISECONDS);
            } catch (RedisConnectionClosedException | RedisResponseTimeoutException e) {
// 如果抛出这类异常,为了防止加锁成功,但是响应失败,需要解锁
                unlockInner(Arrays.asList(lock));
                lockAcquired = false;
            } catch (Exception e) {
// 抛出异常表示获取锁失败
                lockAcquired = false;
            }
            if (lockAcquired) {
// 成功获取锁集合
                acquiredLocks.add(lock);
            } else {
// 如果达到了允许加锁失败节点限制,那么break,即此次Redlock加锁失败
                if (locks.size() - acquiredLocks.size() == failedLocksLimit()) {
                    break;
                }
            }
        }
        return true;
    }

Edit page
Share this post on:

Previous Post
k8s network sdn
Next Post
GTN Intro