基于redis实现分布式锁
废话不多说,直接上代码
public String testOneBuy(){
String value = UUID.randomUUID().toString()+Thread.currentThread().getName();
try {
// 因为加锁和设置过期时间是两步,不具备原子性,例如 加锁成功,服务挂掉,那么锁就永远不会释放
// Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(REDIS_LOCK, value);
// if(flag){
// stringRedisTemplate.expire(REDIS_LOCK,10, TimeUnit.SECONDS);
// }
//改进版本
Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(REDIS_LOCK, value, 10, TimeUnit.SECONDS);
if(!flag){
return "抢锁失败";
}
//执行业务代码处理
}catch (Exception e){
log.error("业务代码异常");
}finally {
// 这里操作是非原子性的,所以官方明确建议使用lua脚本
// if(stringRedisTemplate.opsForValue().get(REDIS_LOCK).equalsIgnoreCase(value)){
// stringRedisTemplate.delete(REDIS_LOCK);
// }
//采用redis事物来解决 redis也支持事物,但是不支持事物回滚
// while (true){
// //开始redis事物的监控
// stringRedisTemplate.watch(REDIS_LOCK);
// if(stringRedisTemplate.opsForValue().get(REDIS_LOCK).equalsIgnoreCase(value)){
//
// //开启事物
// stringRedisTemplate.setEnableTransactionSupport(true);
// stringRedisTemplate.multi();
// stringRedisTemplate.delete(REDIS_LOCK);
// List<Object> exec = stringRedisTemplate.exec();
// if(exec==null){
// continue;
// }
// stringRedisTemplate.unwatch();
// break;
// }
// }
//
// }
Jedis jedis = JedisUtil.getJedis();
String lua="if redis.call(\"get\",KEYS[1]) == ARGV[1]\n" +
"then\n" +
" return redis.call(\"del\",KEYS[1])\n" +
"else\n" +
" return 0\n" +
"end";
try {
Object eval = jedis.eval(lua, Collections.singletonList(REDIS_LOCK), Collections.singletonList(value));
if ("1".equals(eval)) {
log.info("delete lock ok");
}else {
log.info("delete lock erroe");
}
}finally {
if(null==jedis){
jedis.close();
}
}
}
return "成功执行";
}
应该有需要改进的,太晚了,明天改进。