0
点赞
收藏
分享

微信扫一扫

Redis深入理解五 :Redis 分布式锁 以及 Redisson 分析

水墨_青花 2022-03-30 阅读 46
Redis

简单redis锁实现(思考问题)

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    public String testRedisLock() {
		String lockKey = "lock:product:1";
        String clientId = UUID.randomUUID().toString();
        Boolean result = stringRedisTemplate.opsForValue().setIfAbsent(lockKey, clientId, 30, TimeUnit.SECONDS);
        if (!result)
            return "error";

        try {
            //TODO
        } finally {
            if (clientId.equals(stringRedisTemplate.opsForValue().get(lockKey))) {
                stringRedisTemplate.delete(lockKey);
            }
        }
        return "ok";
    }

常规实现

    @Autowired
    private Redisson redisson;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    public String testRedissonLock() {
        String lockKey = "lock:product:1";
        //获取锁对象
        RLock redissonLock = redisson.getLock(lockKey);
        //加分布式锁
        redissonLock.lock();
        try {
            int stock = Integer.parseInt(stringRedisTemplate.opsForValue().get("stock"));
            if (stock > 0) {
                int realStock = stock - 1;
                stringRedisTemplate.opsForValue().set("stock", realStock + "");
                System.out.println("扣减成功,剩余库存:" + realStock);
            } else {
                System.out.println("扣减失败,库存不足");
            }
        } finally {
            //解锁
            redissonLock.unlock();
        }
        return "ok";
    }

Redisson 加锁原理

在这里插入图片描述

Redisson 源码分析

redissonLock.lock();

redissonLock.lock();
redissonLock.lockInterruptibly();
redissonLock.lockInterruptibly(-1L, (TimeUnit)null);
Long ttl = redissonLock.tryAcquire(leaseTime, unit, threadId);
redissonLock.tryAcquireAsync(leaseTime, unit, threadId)
RFuture<Long> ttlRemainingFuture = redissonLock.tryLockInnerAsync(redissonLock.commandExecutor.getConnectionManager().getCfg().getLockWatchdogTimeout(), TimeUnit.MILLISECONDS, threadId, RedisCommands.EVAL_LONG);

<T> RFuture<T> tryLockInnerAsync(long leaseTime, TimeUnit unit, long threadId, RedisStrictCommand<T> command) {
   this.internalLockLeaseTime = unit.toMillis(leaseTime);
   return this.commandExecutor.evalWriteAsync(this.getName(), 
   	LongCodec.INSTANCE, 
   	command, 
   	("if (redis.call('exists', KEYS[1]) == 0) then " +
         "redis.call('hset', 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(this.getName()), 
   	new Object[]{this.internalLockLeaseTime, this.getLockName(threadId)}
  );
}
举报

相关推荐

0 条评论