`
uule
  • 浏览: 6305952 次
  • 性别: Icon_minigender_1
  • 来自: 一片神奇的土地
社区版块
存档分类
最新评论

Redis分布式锁取ID-工具类RedisLock

阅读更多

参考:

https://www.jianshu.com/p/79f2e1d9568c

 

工具类:

import org.apache.log4j.Logger;
import redis.clients.jedis.Jedis;
import com.common.common.RedisCacheUtil;


/**
 * 使用Redis实现的分布式锁
 */
public class RedisLock{
	static Logger logger = Logger.getLogger(RedisLock.class);
	
	private String lockKey;
	private boolean owner = false;
	private boolean waiting = false;
	private int defaltTimeoutMsecs = 60*1000;//锁等待超时时间,以毫秒为单位
	private int defaultExpireMsecs = 60*1000;//锁持有超时时间,以毫秒为单位 
	private boolean expired = false;
	private boolean locked = false;
	private Jedis jedis = null;

	public RedisLock(Jedis jedis, String lockKey) {
		this.jedis = jedis;
		this.lockKey = lockKey;
	}

	/**
	 * 获取分布式锁
	 *
	 * @return true if lock is acquired, false acquire timeouted
	 * @throws InterruptedException
	 *             in case of thread interruption
	 */
	public boolean acquire() throws InterruptedException {
		if(jedis == null){
			return false;
		}
		Long startTime = System.currentTimeMillis();
		int timeout = defaltTimeoutMsecs;
		while (timeout >= 0) {
			long expires = System.currentTimeMillis() + defaultExpireMsecs + 1;
			String expiresStr = String.valueOf(expires); //锁到期时间

			if (jedis.setnx(lockKey, expiresStr) == 1) {
				// lock acquired
				locked = true;
				logger.debug("获取分布式锁成功1,锁key:" + lockKey + ",耗时:" + (System.currentTimeMillis()-startTime));
				return true;
			}

			String currentValueStr = jedis.get(lockKey); //redis里的时间
			if (currentValueStr != null && Long.parseLong(currentValueStr) < System.currentTimeMillis()) {
				//判断是否为空,不为空的情况下,如果被其他线程设置了值,则第二个条件判断是过不去的
				// lock is expired

				String oldValueStr = jedis.getSet(lockKey, expiresStr);
				//获取上一个锁到期时间,并设置现在的锁到期时间,
				//只有一个线程才能获取上一个线上的设置时间,因为jedis.getSet是同步的
				if (oldValueStr != null && oldValueStr.equals(currentValueStr)) {
					//如过这个时候,多个线程恰好都到了这里,但是只有一个线程的设置值和当前值相同,他才有权利获取锁
					// lock acquired
					locked = true;
					logger.debug("获取分布式锁成功2,锁key:" + lockKey + ",耗时:" + (System.currentTimeMillis()-startTime));
					return true;
				}
			}
			timeout -= 100;
			Thread.sleep(100);
			logger.debug("等待获取分布式锁,等待时间:"  + (defaltTimeoutMsecs-timeout));
		}
		logger.info("获取分布式锁失败,锁key:" + lockKey  + ",耗时:" + (System.currentTimeMillis()-startTime));
		return false;
	}

	/**
	 * 释放分布式锁
	 */
	public void release(){
		if(locked){
			jedis.del(lockKey);
			logger.info("释放分布式锁成功,锁key:" + lockKey);
		}
	}
}

 使用:

//锁定
			RedisLock redisLock = new RedisLock(RedisCacheUtil.getResource(),"redis-lock-key");
			boolean ac = false;
			try {
				ac = redisLock.acquire();
			} catch (Exception e1) {
				// TODO Auto-generated catch block
				logger.error("code redis lock error");
				return 0L;
			}
			if(ac){
				// 从数据库中取数据。放缓存				
				redisLock.release();
				
			}else {
				//没有取到锁,说明有进程正往缓存中写数据。 先休眠1秒,再取。
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					logger.error("thread sleep eror");
				}
			}

 

 

..

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics