1.緩存穿透
@Overridepublic 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){//將空值寫入redisstringRedisTemplate.opsForValue().set(key,"",CACHE_NULL_TTL, TimeUnit.MINUTES);return Result.fail("店鋪不存在");}//6.存在,寫入redisstringRedisTemplate.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){//將空值寫入redisstringRedisTemplate.opsForValue().set(key,"",CACHE_NULL_TTL, TimeUnit.MINUTES);return null;}//6.存在,寫入redisstringRedisTemplate.opsForValue().set(key,JSONUtil.toJsonStr(shop));unLock(LOCK_SHOP_KEY);//7.返回return shop;}