1.缓存穿透
@Override
public Result queryById(Long id) {
//1.从redis中查询缓存
String key = CACHE_SHOP_KEY + id;
String shopJson = stringRedisTemplate.opsForValue().get(key);
//2.判断是否存在
//3.存在则直接返回
if (StrUtil.isNotBlank(shopJson)){
Shop shop = JSONUtil.toBean(shopJson, Shop.class);
return Result.ok(shop);
}
//判断是否命中空值
if (shopJson!=null){
return Result.fail("店铺信息不存在");
}
//4.不存在,根据ID查询数据库
Shop shop = getById(id);
//5.不存在,返回错误
if (shop== null){
//将空值写入redis
stringRedisTemplate.opsForValue().set(key,"",CACHE_NULL_TTL, TimeUnit.MINUTES);
return Result.fail("店铺不存在");
}
//6.存在,写入redis
stringRedisTemplate.opsForValue().set(key,JSONUtil.toJsonStr(shop));
//7.返回
return Result.ok(shop);
}
2.缓存雪崩
3.缓存击穿
//缓存击穿
public Shop queryWithMutex(Long id){
//1.从redis中查询缓存
String key = CACHE_SHOP_KEY + id;
String shopJson = stringRedisTemplate.opsForValue().get(key);
//2.判断是否存在
//3.存在则直接返回
if (StrUtil.isNotBlank(shopJson)){
Shop shop = JSONUtil.toBean(shopJson, Shop.class);
return shop;
}
//判断是否命中空值
if (shopJson!=null){
return null;
}
//实现缓存重建
//尝试获取互斥锁
boolean isLock = tryLock(LOCK_SHOP_KEY);
//判断获取互斥锁是否成功
if (!isLock){
//失败,休眠并且重试
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
queryWithMutex(id);
}
//成功
//4.不存在,根据ID查询数据库
Shop shop = getById(id);
//5.不存在,返回错误
if (shop== null){
//将空值写入redis
stringRedisTemplate.opsForValue().set(key,"",CACHE_NULL_TTL, TimeUnit.MINUTES);
return null;
}
//6.存在,写入redis
stringRedisTemplate.opsForValue().set(key,JSONUtil.toJsonStr(shop));
unLock(LOCK_SHOP_KEY);
//7.返回
return shop;
}