您的位置:首页 > 数据库 > Redis

Spring引用Redis分布式锁

2017-12-01 14:55 357 查看
1.redis的两个命令:SETNX 、GETSET

在学习分布式锁之前,首先需要了解一下redis的两个命令:setnx和getset

setnx:设置一个键值对到redis,若redis中已经存在,则无法再次设置进去
getset:获取redis中的一个值得同时设置一个值进去

2.根据setnx和getset的原理,设置对应的分布式锁,代码如下:

private <T> T execute(Function<ShardedJedis, T> function) {
ShardedJedis shardedJedis = null;
try {
// 从连接池中获取到jedis分片对象
shardedJedis = shardedJedisPool.getResource();
return function.execute(shardedJedis);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != shardedJedis) {
// 关闭,检测连接是否有效,有效则放回到连接池中,无效则重置状态
shardedJedis.close();
}
}
return null;
}
//获取锁 name对应锁的key  value对应过期时间 这里也可以设置redis中数据的过期时间
public boolean getLock(final String name,final String value){
return this.execute(new Function<ShardedJedis, Boolean>() {
[@Override](https://my.oschina.net/u/1162528)
public Boolean execute(ShardedJedis shardedJedis) {
Long setnx = shardedJedis.setnx(name, value);
if(setnx==1L){
return true;
}
String oldTimeValue = shardedJedis.get(name);
if(StringUtils.isNotEmpty(oldTimeValue) && System.currentTimeMillis()>Long.valueOf(oldTimeValue)){
String oldTime = shardedJedis.getSet(name,value);
if(StringUtils.isNotEmpty(oldTime)&& oldTime.equals(oldTimeValue)){
return true;
}
}
return false;
}
});
}
//解锁 name对应锁的key  value对应过期时间 这里也可以设置redis中数据的过期时间
public void unLock(final String name,final String value){
this.execute(new Function<ShardedJedis, Boolean>() {
[@Override](https://my.oschina.net/u/1162528)
public Boolean execute(ShardedJedis shardedJedis) {
if(StringUtils.isNotEmpty(name) && StringUtils.isNotEmpty(value)){
String timeValue = shardedJedis.get(name);
if(StringUtils.isNotEmpty(timeValue)&& timeValue.equals(value)){
shardedJedis.del(name);
return true;
}
}
return false;
}
});
}

然后就可以在程序中使用了:

public  void exportStudentSubmitExperimentFileReport(HttpServletResponse response,HttpServletRequest request,Integer[] ids,TeacherInfo teacher) throws Exception{
//这里拿锁的时间
String value = String.valueOf(System.currentTimeMillis()+lock_due_time);
//这里我循环拿锁15次,拿不到就报错
for(int i=1;i<15;i++){
//这里 拿到锁就执行,拿不到锁就循环
if(redisLock.getLock(exportExperimentReport, value)){
List<SubmitExperimentFile> list=	submitExperimentFileMapper.selectsubmitExperimentFileByIds(ids);
List<Map<String, Object>> listMap = this.toHtml(list);
if(listMap!=null && listMap.size()>0){

if(listMap.size()==1){
Html2WorldUtils.html2WorldList(request, response,listMap.get(0));
}else{
Html2WorldUtils.html2WorldList(request, response, listMap,FILE_PATH+VS_EXPERIMENT+"/experiment_reports/"+teacher.getName(),"实验报告");
}
}
updateExportStatusByIds(ids,1);
//解锁
redisLock.unLock(exportExperimentReport, value);
break;
}
if(i>=14){
throw new RuntimeException("导出实验报告的教师过多,请稍后重试");
}
}
}

注意:加锁了之后要记得解锁
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: