java使用redis实现分布式锁

6 篇文章 0 订阅

直接贴上代码

/**
	 * @param subKey  set Key name
	 * @param timeout  get lock timeout,if not get,
	 * @param unit   time unit
	 * @param sValue  
	 * @return
	 */
	 public static boolean tryLock(String subKey, String sValue,long timeout, TimeUnit unit) {  
		  String key =  subKey;  
		  Jedis jedis =  null;
			try {
				jedis = getResource(); 
				if (jedis == null) {
					return Boolean.FALSE;
				}
				long nano = System.nanoTime();
				do {
					logger.debug("try lock key: " + key);
					Long i = jedis.setnx(key, sValue);  //此处可能出现死锁(执行setnx后,redis crash ,key一直存在)
					if (i == 1) {
						jedis.expire(key, 5);//锁失效时间5秒
						logger.debug("get lock, key: " + key + " , expire in "
								+ 2 + " seconds.");
						return Boolean.TRUE;
					} 
					
					//解决出现死锁问题  可优化为 getset方式 重新设置值
					// key存在, 获取key的内容值, 值为nanotime 纳秒   ,当前的时间 - key的值>锁 锁定时间,此时可获取锁
					String value = jedis.get(key);
					if (StringUtils.isNotBlank(value) && 
							!"nil".equalsIgnoreCase(value)&&
							(System.nanoTime()-Long.valueOf(value))>TimeUnit.SECONDS.toNanos(5)) {
						set(key, value, 5); //设置key 5秒过期  自动释放
						return Boolean.TRUE;
					}
					if (timeout == 0) { // 取不到锁时,不等待,直接返回.
						break;
					}
					Thread.sleep((int)(50*Math.random()+50));// 等待50- 100毫秒  避免不同线程竞争时间相同
				} while ((System.nanoTime() - nano) < unit.toNanos(timeout));// 取不到锁时等待,直到timeout
				if (logger.isInfoEnabled()) {
					String desc = jedis.get(key);
					logger.debug("key: " + key
							+ " locked by another business:" + desc);
				}
				return Boolean.FALSE;
			}catch (Exception e) {
				logger.error(e.getMessage(), e);
			} finally {
				returnResource(jedis);//释放连接
			}
		  return Boolean.FALSE;  
		 }  
		 
	 
	 
	 	/** 获取key对应值,对比值内容, 相同则删除,释放锁,避免删除其他线程已经获取的锁
	 	 * @param subKey
	 	 * @param sValue
	 	 */
		public static boolean unLock(String subKey,String sValue) {
			String key =  subKey;
			Jedis jedis = null;
			try {
				jedis = getResource(); 
				if (jedis == null) {
					return false;
				}
				String str = jedis.get(subKey);
				if (str.equals(sValue)) {
					jedis.del(key);
					logger.debug("release lock, keys :" + key);
					return true;
				}else {
					logger.debug("the key is not exist,key : " + key);
				}
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			} finally {
				returnResource(jedis);//释放连接
			}
			return false;
		}
		
		
		public static void main(String args[]){
			String sValue = String.valueOf(System.nanoTime());
			String subKey = "productId";
			try {
				//  5000毫秒 
				boolean lock = tryLock(subKey, sValue, 5000, TimeUnit.MILLISECONDS);
				if (lock) {
					//do job 相关业务逻辑
				}
			} catch (Exception e) {
				e.printStackTrace();
			}finally{
				unLock(subKey, sValue);
			}
			
			
		}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奔跑的窝窝牛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值