Redis分布式锁实现原理 java版

说明:
Redis因为是单线程的,所以本身没有锁的概念。
所以分布式锁的实现原理是 往Redis当中写入一个key(调用方法setnx),写入成功相当于获取锁成功。写入失败也即是setnx方法返回0,获取锁失败。
注意锁的失效时间,否则容易造成死锁。


[java]  view plain  copy
  1. /** 
  2.   * 锁在给定的等待时间内空闲,则获取锁成功 返回true, 否则返回false 
  3.   * @param subKey 
  4.   * @param timeout 如果timeout=0,取不到锁时,不等待,直接返回. 
  5.   * @param unit 
  6.   * @return 
  7.   */  
  8.  public boolean tryLock(String subKey, long timeout, TimeUnit unit) {  
  9.   String key = LOCK_KEY + subKey;  
  10.   Jedis jedis = null;  
  11.   try {  
  12.    jedis = getConnection();  
  13.    if (jedis == null) {  
  14.     return Boolean.FALSE;  
  15.    }  
  16.    long nano = System.nanoTime();  
  17.    do {  
  18.     logger.debug("try lock key: " + key);  
  19.     Long i = jedis.setnx(key, key);  
  20.     if (i == 1) {  
  21.      jedis.expire(key, EXPIRED_TIME);  
  22.      logger.debug("get lock, key: " + key + " , expire in " + EXPIRED_TIME + " seconds.");  
  23.      return Boolean.TRUE;  
  24.     } else { // 存在锁  
  25.      if (logger.isDebugEnabled()) {  
  26.       String desc = jedis.get(key);  
  27.       logger.debug("key: " + key + " locked by another business:" + desc);  
  28.      }  
  29.     }  
  30.     if (timeout == 0) { //取不到锁时,不等待,直接返回.  
  31.      break;  
  32.     }  
  33.     Thread.sleep(200);  
  34.    } while ((System.nanoTime() - nano) < unit.toNanos(timeout));//取不到锁时等待,直到timeout  
  35.    return Boolean.FALSE;  
  36.   } catch (JedisConnectionException je) {  
  37.    logger.error(je.getMessage(), je);  
  38.    returnBorkenConnection(jedis);  
  39.   } catch (Exception e) {  
  40.    logger.error(e.getMessage(), e);  
  41.   } finally {  
  42.    returnConnection(jedis);  
  43.   }  
  44.   return Boolean.FALSE;  
  45.  }  
  46.   
  47.   
  48. /** 
  49.   * 如果锁空闲立即返回   获取失败 一直等待 
  50.   * @param subKey 
  51.   */  
  52.  public boolean lock(String subKey) {  
  53.   String key = LOCK_KEY + subKey;  
  54.   Jedis jedis = null;  
  55.   boolean isLock = false;  
  56.   try {  
  57.    jedis = getConnection();  
  58.    if (jedis == null) {  
  59.     return isLock;  
  60.    }  
  61.    while (true) {  
  62.     logger.debug("lock key: " + key);  
  63.     Long i = jedis.setnx(key, key);  
  64.     if (i == 1) {  
  65.      jedis.expire(key, EXPIRED_TIME);  
  66.      logger.debug("get lock, key: " + key + " , expire in " + EXPIRED_TIME + " seconds.");  
  67.      isLock = true;  
  68.     } else {  
  69.      if (logger.isDebugEnabled()) {  
  70.       String desc = jedis.get(key);  
  71.       logger.debug("key: " + key + " locked by another business:" + desc);  
  72.      }  
  73.      isLock = false;  
  74.     }  
  75.     Thread.sleep(500);  
  76.    }  
  77.   } catch (JedisConnectionException je) {  
  78.    logger.error(je.getMessage(), je);  
  79.    returnBorkenConnection(jedis);  
  80.   } catch (Exception e) {  
  81.    logger.error(e.getMessage(), e);  
  82.   } finally {  
  83.    returnConnection(jedis);  
  84.   }  
  85.   return isLock;  
  86.  }  
  87. /** 
  88.   * 释放锁 
  89.   * @param subKey 
  90.   */  
  91.  public void unLock(String subKey) {  
  92.   String key = LOCK_KEY + subKey;  
  93.   Jedis jedis = null;  
  94.   try {  
  95.    jedis = getConnection();  
  96.    if (jedis == null) {  
  97.     return;  
  98.    }  
  99.    jedis.del(key);  
  100.    logger.debug("release lock, keys :" + key);  
  101.   } catch (JedisConnectionException je) {  
  102.    logger.error(je.getMessage(), je);  
  103.    returnBorkenConnection(jedis);  
  104.   } catch (Exception e) {  
  105.    logger.error(e.getMessage(), e);  
  106.   } finally {  
  107.    returnConnection(jedis);  
  108.   }  
  109.  }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值