使用redis setnx命令结合lua脚本实现分布式锁功能
public Map<String, List<catalog2Vo>> getCatalogJsonFromDBWithRedisLock() {
//抢占分布式锁
String uuid = UUID.randomUUID().toString();//设置锁的唯一id
Boolean lockBoolean = redisTemplate.opsForValue().setIfAbsent("redisLock",uuid,60,TimeUnit.SECONDS);//设置过期时间,这里的setIfAbsent相当于setnx命令
if (lockBoolean){
System.out.println("success to obtain redisLock");
//加锁成功,执行业务,设置过期时间,与加锁同步,获取锁与删除锁这两个步骤须是原子操作,结合lua脚本操作
Map<String, List<catalog2Vo>> dataFromDB;
try{
dataFromDB = getDataFromDB();//业务逻辑
}
finally {//释放锁
String script="if redis.call(\"get\",KEYS[1]) == ARGV[1]\n" +
"then\n" +
" return redis.call(\"del\",KEYS[1])\n" +
"else\n" +
" return 0\n" +
"end";
redisTemplate.execute(new DefaultRedisScript<>(script,Long.class),Arrays.asList("redisLock"),uuid);
}
return dataFromDB;
}else {
//加锁失败,重试
System.out.println("fail to obtain the redisLock,ready to repeated...");
try{
Thread.sleep(200);
}catch (Exception e){
System.out.println(e.getStackTrace());
}
return getCatalogJsonFromDBWithRedisLock();
}
}