redis 分布式锁

redis 分布式锁 

实现命令是 setnx key true expire key 5 5秒后过期del key 

死锁问题 :setnx和expire的组合命令set key true ex 5 nx超时问题 :Redis 的分布式锁不能解决超时问题,如果在加锁和释放锁之间的逻辑执行的太长,以至于超出了锁的超时限制,就会出现问题。因为这时候锁过期了,第二个线程重新持有了这把锁,但是紧接着第一个线程执行完了业务逻辑,就把锁给释放了,第三个线程就会在第二个线程逻辑执行完之间拿到了锁。解决方案 : 根据需要设置超时时间大小 / 给key 对应的value 加上随机数,在释放锁之前判断随机数是不是一致的 。可重入性问题:不推荐使用可重入锁,加重了客户端的复杂性

java redis可重入锁的实现 

public class RedisWithReentrantLock { private ThreadLocal> lockers = new ThreadLocal<>(); private Jedis jedis; public RedisWithReentrantLock(Jedis jedis) { this.jedis = jedis; } private boolean _lock(String key) { return jedis.set(key, "", "nx", "ex", 5L) != null; } private void _unlock(String key) { jedis.del(key); } private MapcurrentLockers() { Maprefs = lockers.get(); if (refs != null) { return refs; } lockers.set(new HashMap<>()); return lockers.get(); } public boolean lock(String key) { Maprefs = currentLockers(); Integer refCnt = refs.get(key); if (refCnt != null) { refs.put(key, refCnt + 1); return true; } boolean ok = this._lock(key); if (!ok) { return false; } refs.put(key, 1); return true; }public boolean unlock(String key) { Map refs = currentLockers();

    Integer refCnt = refs.get(key);

    if (refCnt == null) {

      return false;

    }

    refCnt -= 1;

    if (refCnt > 0) {

      refs.put(key, refCnt);

    } else {

      refs.remove(key);

      this._unlock(key);

    }

    return true;

  }

  public static void main(String[] args) {

    Jedis jedis = new Jedis();

    RedisWithReentrantLock redis = new RedisWithReentrantLock(jedis);

    System.out.println(redis.lock("codehole"));

    System.out.println(redis.lock("codehole"));

    System.out.println(redis.unlock("codehole"));

    System.out.println(redis.unlock("codehole"));

  }

}

你可能感兴趣的:(redis 分布式锁)