RFuture tryLockInnerAsync(long waitTime, long leaseTime, TimeUnit unit, long threadId, RedisStrictCommand command) { return evalWriteAsync(getName(), LongCodec.INSTANCE, command, "if (redis.call('exists', KEYS[1]) == 0) then " + "redis.call('hincrby', KEYS[1], ARGV[2], 1); " + "redis.call('pexpire', KEYS[1], ARGV[1]); " + "return nil; " + "end; " + "if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " + "redis.call('hincrby', KEYS[1], ARGV[2], 1); " + "redis.call('pexpire', KEYS[1], ARGV[1]); " + "return nil; " + "end; " + "return redis.call('pttl', KEYS[1]);", Collections.singletonList(getName()), unit.toMillis(leaseTime), getLockName(threadId)); } 此处的LockName UUID是基于当前时间、计数器(counter)和硬件标识(通常为无线网卡的MAC地址)等数据计算生成的。
protected String getLockName(long threadId) { return id + ":" + threadId;}this.id = commandExecutor.getConnectionManager().getId();// debug 发现id是一个 uuid// 所以不会出现不同服务相同线程id对redis分布式锁上锁成功的情况加锁流程图
Redisson Lock的效果
watchdog 锁自动续期(默认每次续30s)
private void renewExpiration() { ExpirationEntry ee = EXPIRATION_RENEWAL_MAP.get(getEntryName()); if (ee == null) { return; } Timeout task = commandExecutor.getConnectionManager().newTimeout(new TimerTask() { @Override public void run(Timeout timeout) throws Exception { ExpirationEntry ent = EXPIRATION_RENEWAL_MAP.get(getEntryName()); if (ent == null) { return; } Long threadId = ent.getFirstThreadId(); if (threadId == null) { return; } // 锁续期 RFuture future = renewExpirationAsync(threadId); future.onComplete((res, e) -> { // 异常 if (e != null) { log.error("Can't update lock " + getName() + " expiration", e); EXPIRATION_RENEWAL_MAP.remove(getEntryName()); return; } if (res) { // reschedule itself // 续期成功,再提交一个任务 renewExpiration(); } }); } }, internalLockLeaseTime / 3, TimeUnit.MILLISECONDS); ee.setTimeout(task);}// 主要判断就是 这个锁是否在 redis 中存在,如果存在就进行 pexpire 延期protected RFuture renewExpirationAsync(long threadId) { return evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN, "if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then " + "redis.call('pexpire', KEYS[1], ARGV[1]); " + "return 1; " + "end; " + "return 0;", Collections.singletonList(getName()), internalLockLeaseTime, getLockName(threadId));} Redisson分布式锁安全的原因: 首先锁的lockName是根据uuid+当前线程id组合生成,不可能存在重复 同时还有一个watch dog自动续期的机制
| 留言与评论(共有 0 条评论) “” |