要想使用redis分布式锁很好地支撑我们的业务
需要确保:
1.加锁要保证原子性;
2.解锁要保证原子性。
示例代码:
public Map<String, List<Catelog2Vo>> getCatelogJsonFromDbWithRedisLock() {//使用redis分布式锁,防止缓存击穿String uuid = UUID.randomUUID().toString();Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock",uuid,300,TimeUnit.SECONDS);Map<String, List<Catelog2Vo>>map;if(lock){//如果加锁成功,执行业务System.out.println("获取分布式锁成功...........");map = getDataFromDb();try {} finally {//执行完业务,要释放锁,使用delete解锁,非原子性,存在缺陷// 获取值对比+对比成功删除=原子操作// String lockValue = redisTemplate.opsForValue().get("lock");// if (uuid.equals(lockValue)) {// redisTemplate.delete("lock");// }// 使用lua脚本解锁,保证原子性String script = "if redis.call('get',KEYS[1]) == ARGV[1] then return redis.call('del',KEYS[1]) else return 0 end";Long unlock = redisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class), Arrays.asList("lock"), uuid);}return map;}else{//加锁失败,重试,执行类似syncronized方法,自旋锁,等待->重试System.out.println("获取分布式锁失败........等待重试");//可以添加休眠时间try {Thread.sleep(100);} catch (InterruptedException e) {throw new RuntimeException(e);}return this.getCatelogJsonFromDbWithRedisLock();}}