Spring引用Redis分布式锁
2017-12-01 14:55
357 查看
1.redis的两个命令:SETNX 、GETSET
setnx:设置一个键值对到redis,若redis中已经存在,则无法再次设置进去
getset:获取redis中的一个值得同时设置一个值进去
2.根据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("导出实验报告的教师过多,请稍后重试"); } } }
注意:加锁了之后要记得解锁
相关文章推荐
- spring如何引用properties文件里的配置
- maven构建项目引用spring找不到org.springframework.transaction
- spring Boot jar包工程下引用静态资源
- java的Spring学习1--spring引用及属性(setter,getter)注入
- 学习Spring(五) -- Spring的配置文件引用
- 第六章:Spring Boot log4j2日志引用(三)
- Spring包结构以及各个包之间引用关系说明
- Spring 实现引用对象中值的注入
- (7)spring依赖注入引用其它Bean
- SPRING.NET 1.3.2 学习14--复合属性名称和Spring表达式的引用
- spring中引用多个配置文件
- spring property value 引用properties文件和直接设置的区别
- maven引用jar报错:spring-core:jar must be a valid version but is '${spring.version}
- Springboot引用外部配置文件
- maven Springmvc-jsp页面引用js css images静态资源文件
- Spring引用Tomcat的 JTA事务
- Spring使用注解的方式配置bean的属性-bean之间的引用关系
- Spring4之Bean之间的关系(继承、依赖、引用)Bean的作用范围
- spring框架(一)——Spring核心框架体系结构(jar包引用分析)
- 4000 spring 对静态资源的引用