分布式锁原理与使用
public Map<Long, List<Catalog2Vo>> getCatalogJson() {
String catalogJson = stringRedisTemplate.opsForValue().get("CatalogJson");
if (StringUtils.isEmpty(catalogJson)) {
// redis 分布式锁
String uuid = UUID.randomUUID().toString();
// 抢占锁 和设置时间必须是原子性的
Boolean lock = stringRedisTemplate.opsForValue().setIfAbsent("lock", uuid, 300, TimeUnit.SECONDS);
Map<Long, List<Catalog2Vo>> map = null;
if (lock) {
// 为 true 说明获取分布式锁成功
//获取一级分类
// 加锁解决缓存穿透的问题
List<CategoryEntity> categoryOneLevel = this.getCategoryOneLevel();
// 组装结果返回
try {
map = getCatalogListMapWithRedisLock(categoryOneLevel);
// 存到缓存中
String s = JSON.toJSONString(map);
// 设置不通的时间返回缓存雪崩的问题
stringRedisTemplate.opsForValue().set("CatalogJson", s, 1, TimeUnit.DAYS);
} finally {
// lun 脚本
String script = "if redis.call(\"get\",KEYS[1]) == ARGV[1] then\n" +
" return redis.call(\"del\",KEYS[1])\n" +
"else\n" +
" return 0\n" +
"end";
// Arrays.asList("lock") ==== KEYS[1] uuid ==== ARGV[1] lua脚本保证判断key和删除key的原子性操作
Long lock1 = stringRedisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class), Arrays.asList("lock"), uuid);
}
return map;
} else {
// 获取失败 从新执行
getCatalogJson();
}
}
return JSON.parseObject(catalogJson, new TypeReference<Map<Long, List<Catalog2Vo>>>() {
});
}