网站建设服务器
Redis setnx命令
Redis setnx命令功能
仅当指定的键不存在时设置。换句话说,如果您返回1,则您的命令被成功执行,redis服务器中的密钥是您之前设置的值。如果返回0,则意味着您设置的密钥已经存在于redis服务器中。
status=jedis.setnx(lockKey,redidentitykey);/* *设置锁定键。*/
if(状态0){
expire=jedis.expire(lockKey,lockKeyExpireSecond);/* * setrediskeexpiretime。*/
}
如果设置成功,请设置过期时间,以防止您的重试锁重复设置此过期时间,该过期时间永远不会过期。
Java对象条件队列条件队列
这里有一个小技巧,可以尽可能最大化cpu利用率,解决公平性问题。
当您频繁重试时,要么while(true)无休止地循环,然后添加一个Thread.sleep或CAS。前者有一定的线程上下文切换开销(Thread.sleep不会释放当前内置锁),而CAS在不清楚远程锁被占用多长时间的情况下,会浪费大量的CPU计算周期。有可能一个任务要十几分钟才能算完,CPU不可能闲置这么久。
这里我尝试用条件队列特性来实现(当然肯定还有其他更好的方法)。
if(isWaitretryCountsRetryCount){
retryCounts
Synchronized(this){//通过objectconditionqueue提高CPU利用率。
Logger.info(String.format(t:%s,当前节点:%s,尝试等待锁:%s,thread.currentthread()。getid()、getredidentitykey());
this . wait(WaitLockTimeSecond);//无法获取锁,请等待指定的时间,然后重试。
}
} else if(retry counts==retry count){
Logger.info(String.format(t:%s,当前节点:%s,未能在指定时间内获取锁:%s,thread.currentthread()。getid()、getredidentitykey()、lock key));返回false;
} else { returnfalse//不用等待直接退出。
}
使用条件队列的好处是,虽然释放了CPU,但不会持有当前的synchronized,这样其他并发线程也可以获得当前的内置锁,形成队列。当等待时间结束时,将重新应用同步锁。
简单来说,你不会在锁里等,而是在队列里等。java object的每个对象都持有一个条件队列,它与当前的内置锁一起使用。
Retrycount有重试限制。
等待远程redis锁肯定需要一定的重试机制,但是这种重试需要一定的限制。
/**
*可以根据当前任务的执行时间来设置重试获取锁的次数。
*所需时间=重试次数* (waitlocktimesecond/1000)
*/
privatestaticfinantirtrycount=10;
这种等待需要由用户指定,如果(isWait Retry Counties Retry Count),当isWait为true时将重试。
对象等待时间超时等待
Object.wait(timeout),条件队列中的方法wait需要一个waittime。
/**
*获取锁的等待时间可以根据当前任务的执行时间来设置。
*设置太短,浪费CPU,设置太长锁定不公平。
*/
privatesticfinallowaitlocktimesecond=2000;
默认值为2000毫秒。
this . wait(WaitLockTimeSecond);//无法获取锁,请等待指定的时间,然后重试。
注意:虽然this.wait会阻塞,但是这里的内置锁会被立即释放。所以,有时候我们可以利用这个特性来优化特殊场景。
删除锁定删除远程锁定
释放redis锁比较容易,del键就行。
long status=jedis . del(lock key);if(状态0){
Logger.info(String.format(t:%s,当前节点:%s,锁释放:%s成功。Thread.currentThread()。getId()、getRedisIdentityKey()、lock key));returntrue
}
一旦删除,首先等待的线程将获得锁。
获取锁申请锁
/**
*超时重锁。
*
* @ paramlockKeyExpireSecond过去时间内redis中的锁密钥。
* @ paramlockKeylockkey
*@paramisWait取不到锁的时候需要等待吗?
* @ throwsexception lockkeyisemptythrowexception。
*/
public boolaranaquileckwith time out(intleye xpiresecond,StringlockKey,boolean anitary)抛出异常{ if(string utils。isempty(lock key))throw new exception(lock key mpty).);
intretrycounts=0while(true)}
长状态,expire=0l
status=jedis.setnx(lockKey,重定向密钥):/**设置锁定键(锁定密钥)。*/
如果(状态0)}
过期=jedis。过期(锁键,锁键第二过期);/* * setrediskeexpiretime .*/
}如果(状态0到期0)}
logger.info(字符串)。
格式(t:%s,当前节点:%s,获取到锁用法:%s,Thread.currentThread().getId()、getredisidentitykey()、lock key));返回真:/**获取到锁*/
}请尝试{ if(iswaitretrycountsretrycount)}
退约;
同步(这个){//借助对象条件队列-物件条件伫列来提高中央处理器利用率
logger.info(字符串)。
格式(t:%s,当前节点:%s,尝试等待获取锁用法:%s,Thread.currentThread().getId()、getredisidentitykey()、lock key));这。等待(等待锁定时间秒);//未能获取到锁紧,进行指定时间的等一下再重试。
}
} else if(retry counts==retry count)}
logger.info(字符串)。
格式(t:%s,当前节点:%s,指定时间内获取锁失败用法:%s,Thread.currentThread().getId()、getredisidentitykey()、lock key));返回假的;
}否则{返回else//不需要等待,直接退出。
}
} catch(interruptedexception)}
e。print stack trace();
}
}
}
"李亚锁"释放锁定/**
*释放瑞斯洛克。
*
* @ paramlockKeylockkey
* @ throwseceptionadviseemptythrweexception .
*/
public boolean name elesellockwithtime out(string lock key)throw exception { if(string utils。isempty(lock key))throw new exception(lockkeympty).);
long status=jedis . del(lock key):if(状态0)}
logger.info(String.format(当前节点:%s,释放锁:%s成功getredisidentitykey()、lock key);返回真实:
}
logger.info(String.format(当前节点:%s,释放锁:%s失败getredisidentitykey()、lock key);返回假的;
}
演示文稿演示
2017-06-18 13:57:43.867信息1444 - [nio-8080-exec-1]c . plen。开源。实施者。redislocker:t:23,当前节点:5f 81 f 482-295 a-4394-b8 CB-d 7282和51dd6e,获取到锁:产品:10100101:购物
信息1444 - [nio-8080-exec-3]c . plen。开源。实施者。redislocker:t:25,当前节点:5f 81 f 482-295 a-4394-b8 CB-d 7282和51dd6e,尝试等待获取锁:产品:10100101:购物
2017-06-18 13:57:49.063信息1444 - [nio-8080-exec-3]c . plen。开源。实施者。redislocker:t:25,当前节点:5f 81 f 482-295 a-4394-b8 CB-d 7282和51dd6e,尝试等待获取锁:产品:10100101:购物
2017-06-18 13:57:51.064信息1444 - [nio-8080-exec-3]c . plen。开源。实施者。redislocker:t:25,当前节点:5f 81 f 482-295 a-4394-b8 CB-d 7282和51dd6e,尝试等待获取锁:产品:10100101:购物
2017-06-18 13:57:53 066信息1444 - [nio-8080-exec-3]c . plen。开源。实施者。redislocker:t:25,当前节点:5f 81 f 482-295 a-4394-b8 CB-d 7282和51dd6e,尝试等待获取锁:产品:10100101:购物
2017-06-18 13:57:55.068信息1444 - [nio-8080-exec-3]c . plen。开源。实施者。redislocker:t:25,当前节点:5f 81 f 482-295 a-4394-b8 CB-d 7282和51dd6e,尝试等待获取锁:产品:10100101:购物
2017-06-18 13:57:57.069信息1444 - [nio-8080-exec-3]c . plen。开源。实施者。redislocker:t:25,当前节点:5f 81 f 482-295 a-4394-b8 CB-d 7282和51dd6e,尝试等待获取锁:产品:10100101:购物
2017-06-18 13:57:59.070信息1444 - [nio-8080-exec-3]c . plen。开源。实施者。redislocker:t:25,当前节点:5f 81 f 482-295 a-4394-b8 CB-d 7282和51dd6e,尝试等待获取锁:产品:10100101:购物
2017-06-18 13:58:01.071信息1444 - [nio-8080-exec-3]c . plen。开源。实施者。redislocker:t:25,当前节点:5f 81 f 482-295 a-4394-b8 CB-d 7282和51dd6e,尝试等待获取锁:产品:10100101:购物
信息1444 - [nio-8080-exec-3]c . plen。开源。实施者。redislocker:t:25,当前节点:5f 81 f 482-295 a-4394-b8 CB-d 7282和51dd6e,尝试等待获取锁:产品:10100101:购物
2017-06-18 13:58:05.073信息1444—[nio-8080-exec-3]c . plen。开源。实施。redisker:t:25,当前节点:5 f81 f 482-295 a-4394-b8cb-d 7282 e 51 DD 6 e,尝试等待获取锁:商品编号:10100101:购物
2017-06-18 13:58:07.074信息1444—[nio-8080-exec-3]c . plen。开源。实施。redisker:t:25,当前节点:5 f81 f 482-295 a-4394-b8cb-d 7282 e 51 DD 6 e,指定时间内获取锁失败:商品编号:10100101:购物
2017-06-18 13:58:23.768信息1444—[nio-8080-exec-6]c . plen。开源。实施。redisker:t:28,当前节点:5 f81 f 482-295 a-4394-b8cb-d 7282 e 51 DD 6 e,尝试等待获取锁:商品编号:10100101:购物
2017-06-18 13:58:25.769信息1444—[nio-8080-exec-6]c . plen。开源。实施。redisker:t:28,当前节点:5 f81 f 482-295 a-4394-b8cb-d 7282 e 51 DD 6 e,尝试等待获取锁:商品编号:10100101:购物
2017-06-18 13:58:27.770信息1444—[nio-8080-exec-6]c . plen。开源。实施。redisker:t:28,当前节点:5 f81 f 482-295 a-4394-b8cb-d 7282 e 51 DD 6 e,尝试等待获取锁:商品编号:10100101:购物
2017-06-18 13:58:29.772信息1444—[nio-8080-exec-6]c . plen。开源。实施。redisker:t:28,当前节点:5 f81 f 482-295 a-4394-b8cb-d 7282 e 51 DD 6 e,尝试等待获取锁:商品编号:10100101:购物
2017-06-18 13:58:31.773信息1444—[nio-8080-exec-6]c . plen。开源。实施。redisker:t:28,当前节点:5 f81 f 482-295 a-4394-b8cb-d 7282 e 51 DD 6 e,尝试等待获取锁:商品编号:10100101:购物
2017-06-18 13:58:33.774信息1444—[nio-8080-exec-6]c . plen。开源。实施。redisker:t:28,当前节点:5 f81 f 482-295 a-4394-b8cb-d 7282 e 51 DD 6 e,尝试等待获取锁:商品编号:10100101:购物
2017-06-18 13:58:35.774信息1444—[nio-8080-exec-6]c . plen。开源。实施。redisker:t:28,当前节点:5 f81 f 482-295 a-4394-b8cb-d 7282 e 51 DD 6 e,获取到锁:商品编号:10100101:购物
螺纹23优先获取到对商品ID 10100101进行修改,所以先锁住当前商品。
t:23,当前节点:843 d3ec 0-9c 22-4d 8a-bcaa-745 DBA 35 b 8 a 4,获取到锁:商品编号:10100101:购物
紧接着,螺纹25也来对当前商品10100101进行修改,所以在尝试获取锁。
2017-06-18 13:50:11.021信息4616—[nio-8080-exec-3]c . plen。开源。实施。redisker:t:25,当前节点:946 b 7250-29 F3-459 b-8320-62d 31e 6 f1 fc 4,尝试等待获取锁:商品编号:10100101:购物
2017-06-18 13:50:13.023信息4616—[nio-8080-exec-3]c . plen。开源。实施。redisker:t:25,当前节点:946 b 7250-29 F3-459 b-8320-62d 31e 6 f1 fc 4,尝试等待获取锁:商品编号:10100101:购物
2017-06-18 13:50:15.026信息4616—[nio-8080-exec-3]c . plen。开源。实施。redisker:t:25,当前节点:946 b 7250-29 F3-459 b-8320-62d 31e 6 f1 fc 4,尝试等待获取锁:商品编号:10100101:购物
2017-06-18 13:50:17.028信息4616—[nio-8080-exec-3]c . plen。开源。实施。redisker:t:25,当前节点:946 b 7250-29 F3-459 b-8320-62d 31e 6 f1 fc 4,尝试等待获取锁:商品编号:10100101:购物
2017-06-18 13:50:19.030信息4616—[nio-8080-exec-3]c . plen。开源。实施。redisker:t:25,当前节点:946 b 7250-29 F3-459 b-8320-62d 31e 6 f1 fc 4,尝试等待获取锁:商品编号:10100101:购物
2017-06-18 13:50:21.031信息4616—[nio-8080-exec-3]c . plen。开源。实施。redisker:t:25,当前节点:946 b 7250-29 F3-459 b-8320-62d 31e 6 f1 fc 4,尝试等待获取锁:商品编号:10100101:购物
2017-06-18 13:50:23.035信息4616—[nio-8080-exec-3]c . plen。开源。实施。redisker:t:25,当前节点:946 b 7250-29 F3-459 b-8320-62d 31e 6 f1 fc 4,尝试等待获取锁:商品编号:10100101:购物
2017-06-18 13:50:25.037信息4616—[nio-8080-exec-3]c . plen。开源。实施。redisker:t:25,当前节点:946 b 7250-29 F3-459 b-8320-62d 31e 6 f1 fc 4,尝试等待获取锁:商品编号:10100101:购物
2017-06-18 13:50:27.041信息4616—[nio-8080-exec-3]c . plen。开源。实施。redisker:t:25,当前节点:946 b 7250-29 F3-459 b-8320-62d 31e 6 f1 fc 4,尝试等待获取锁:商品编号:10100101:购物
2017-06-18 13:50:29.042信息4616—[nio-8080-exec-3]c . plen。开源。实施。redisker:t:25,当前节点:946 b 7250-29 F3-459 b-8320-62d 31e 6 f1 fc 4,尝试等待获取锁:商品编号:10100101:购物
2017-06-18 13:50:35.289 INFO 4616—[nio-8080-exec-3]c . plen。开源。实施。redisker:t:25,当前节点:946 b 7250-29 F3-459 b-8320-62d 31e 6 f1 fc 4,指定时间内获取锁失败:商品编号:10100101:购物
在进行了retry10次(2000毫秒,2秒)之后,获取失败,直接返回,等待下次任务调度开始。
2017-06-18 13:58:07.074信息1444—[nio-8080-exec-3]c . plen。开源。实施。redisker:t:25,当前节点:5 f81 f 482-295 a-4394-b8cb-d 7282 e 51 DD 6 e,指定时间内获取锁失败:商品编号:10100101:购物
2017-06-18 13:58:23.768信息1444—[nio-8080-exec-6]c . plen。开源。实施。redisker:t:28,当前节点:5 f81 f 482-295 a-4394-b8cb-d 7282 e 51 DD 6 e,尝试等待获取锁:商品编号:10100101:购物
2017-06-18 13:58:25.769信息1444—[nio-8080-exec-6]c . plen。开源。实施。redisker:t:28,当前节点:5 f81 f 482-295 a-4394-b8cb-d 7282 e 51 DD 6 e,尝试等待获取锁:商品编号:10100101:购物
2017-06-18 13:58:27.770信息1444—[nio-8080-exec-6]c . plen。开源。实施。redisker:t:28,当前节点:5 f81 f 482-295 a-4394-b8cb-d 7282 e 51 DD 6 e,尝试等待获取锁:商品编号:10100101:购物
2017-06-18 13:58:29.772信息1444—[nio-8080-exec-6]c . plen。开源。实施。redisker:t:28,当前节点:5 f81 f 482-295 a-4394-b8cb-d 7282 e 51 DD 6 e,尝试等待获取锁:商品编号:10100101:购物
2017-06-18 13:58:31.773信息1444—[nio-8080-exec-6]c . plen。开源。实施。redisker:t:28,当前节点:5 f81 f 482-295 a-4394-b8cb-d 7282 e 51 DD 6 e,尝试等待获取锁:商品编号:10100101:购物
2017-06-18 13:58:33.774信息1444—[nio-8080-exec-6]c . plen。开源。实施。redisker:t:28,当前节点:5 f81 f 482-295 a-4394-b8cb-d 7282 e 51 DD 6 e,尝试等待获取锁:商品编号:10100101:购物
2017-06-18 13:58:35.774信息1444—[nio-8080-exec-6]c . plen。开源。实施。redisker:t:28,当前节点:5 f81 f 482-295 a-4394-b8cb-d 7282 e 51 DD 6 e,获取到锁:商品编号:10100101:购物
螺纹28发起对商品10100101 进行修改,重试6次之后获取到锁定。
更多关于云服务器,域名注册,虚拟主机的问题,请访问西部数码代理商官网:www.chenqinet.cn