深入了解Redission分布式锁

文章目录

  • 1. 分布式锁的条件
  • 2. 实现分布式锁的方案
  • 3. Redission分布式锁原理
  • 4.场景应用

 现在我们采用的系统都是分布式,比如我们Sychnized上锁,因为他是JVM层面的,所以如果是两台机器的话,这时候它就无能为力了,这时候我们可以用Reddisson。

1. 分布式锁的条件

  • 互斥性
  • 高效性
  • 支持阻塞和非阻塞
  • 支持公平锁和非公平锁

2. 实现分布式锁的方案

  1. .数据库实现(乐观锁)
  2. ZK(借鉴Node的临时顺序节点)
  3. Redission

3. Redission分布式锁原理

 当线程1获取到锁以后,Redission底层有一个watch dog(看门口)会一直检测着,假如现线程1还持有锁,然后就会延长锁时间;这时候线程2来了一个,一直while循环,指导获取到锁;
深入了解Redission分布式锁_第1张图片

源码认证:

  RFuture tryLockInnerAsync(long leaseTime, TimeUnit unit, long threadId, RedisStrictCommand command) {
        internalLockLeaseTime = unit.toMillis(leaseTime);

        return commandExecutor.evalWriteAsync(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(getName()), internalLockLeaseTime, getLockName(threadId));
    }
 
  
  1. KEYS[1] :获取的锁
  2. ARGV[2]::获取锁的那个线程
  3. ARGV[1]: 获取锁的时间

上面是一段lua脚本,其具体的意思是:

  1. 判断有key KEYS[1])是否存在
  2. 如果没有,则设定hash值,大key是KEYS[1]),value是键值对为“ARGV[2], 1)”,并且设定过期时间
  3. 如果存在,然后判断 大key–KEYS[1])下面的小key–ARGV[2]是否存在,如果存在,则在其值上加1,并且重新设定过期时间
  4. 返回过期时间;

4.场景应用

 比如双11进行促销,商品在减库存的时候,我们可以进行运用;下面是一个小demo;

  String product_002="stock";
        //获取锁对象
      RLock redissLock=   redisson.getLock(product_002);
       try {
           //相当于:stringRedisTemplate.opsForValue().setIfAbsent(K key, V value, long timeout, TimeUnit unit);
           //上锁
           redissLock.lock();
           int stock=Integer.parseInt(stringRedisTemplate.opsForValue().get(product_002));
           if(stock>0){
               stock=stock-1;
               stringRedisTemplate.opsForValue().set(product_002,stock+"");
               System.out.println("库存扣减成功:"+stock);
           }else{
               System.out.println("库存不足!");
           }
       }finally {
           //redission 释放锁
           redissLock.unlock();
       }

       return  "end";

   }

你可能感兴趣的:(redis)