Redis SETNX命令实现分布式锁
2017-04-25 18:27
417 查看
SETNX命令简介
命令格式SETNX key value
将 key 的值设为 value,当且仅当 key 不存在。
若给定的 key 已经存在,则 SETNX 不做任何动作。
SETNX 是SET if Not eXists的简写。
返回值
设置成功,返回 1 。
设置失败,返回 0 。
使用SETNX实现分布式锁
/** * 使用Redis实现分布式全局锁 * 算法实现参考:http://redis.io/commands/setnx * @author shenhaiwen * */ public class RedisDistributeLock { private String lockName; private long expireTime; private RedisOperator redisOper; /** * * @param lockName 同一个名称表示同一把锁 * @param expireTime 锁的超时时间,如果超过,该锁失效,其他线程可获取锁 * @param redisOper */ public RedisDistributeLock(String lockName,long expireTime,RedisOperator redisOper){ this.lockName = lockName; this.redisOper = redisOper; this.expireTime = expireTime * 1000; } private String getLockKey(){ if(StringUtils.isBlank(lockName)) return null; return "lock:" + lockName; } /** * 抛出异常或返回-1,说明未获取到锁 * return: 返回值需要在unlock时作为参数传入 * @param timeout -1:永久等待 * @throws Exception */ public long lock(long timeout) throws Exception{ String key = getLockKey(); if(key == null) throw new Exception("lock must have a name"); boolean infinite = (timeout == -1); while(infinite || timeout >= 0){ Long value = System.currentTimeMillis() + expireTime; long keyTimeout = value.longValue(); long setnxRet = redisOper.insertKeyValueIfNotExist(key, value.toString(), -1, null); if(setnxRet > 0){ return keyTimeout; //暂无其他线程或进程加锁 } if(setnxRet == -1){ return -1; } //已经有锁了 String val = redisOper.getValueByKey(key); if(StringUtils.isBlank(val)){ //key刚好被删除了,重来 continue; } if(System.currentTimeMillis() > Long.parseLong(val)){ Long newVal = System.currentTimeMillis() + expireTime; String oldVal = redisOper.getset(key, newVal.toString(), -1, null); if(StringUtils.isBlank(val)){ //key刚好被删除了,重来 continue; } if(System.currentTimeMillis() > Long.parseLong(oldVal)){ keyTimeout = newVal.longValue(); return keyTimeout; } } } if(!infinite){ timeout -= 100; } Thread.sleep(100); return -1; } /** * * @param keyTimeout lock的返回值 */ public void unlock(long keyTimeout){ if(System.currentTimeMillis() > keyTimeout){ return; } redisOper.deleteKeyValue(getLockKey()); } public String getLockName() { return lockName; } public long getExpireTime() { return expireTime; } }
相关文章推荐
- 使用Redis SETNX 命令实现分布式锁
- Redis SETNX 命令实现分布式锁
- 【Redis】 redis setnx命令实现分布式锁
- 详解使用Redis SETNX 命令实现分布式锁
- 使用Redis SETNX 命令实现分布式锁
- 实现分布式锁:Redis SETNX 命令
- 使用Redis SETNX 命令实现分布式锁
- 使用Redis SETNX 命令实现分布式锁
- 使用Redis SETNX 命令实现分布式锁
- 使用Redis SETNX 命令实现分布式锁
- 使用Redis SETNX 命令实现分布式锁
- 使用Redis SETNX 命令实现分布式锁
- 使用Redis SETNX 命令实现分布式锁
- 使用Redis SETNX 命令实现分布式锁
- 基于Redis setNX 实现分布式锁
- 使用Redis SETNX 命令实现分布式锁(转载)
- redis setnx 实现分布式锁和单机锁
- JS实现浏览器菜单命令
- 如何利用jgroups实现分布式环境下消息的接受和发送
- JAVA实现调用本地命令