目錄
問題一: 緩存穿透
說明: 利用redis與mysql數據庫的機制(redis中一旦不存在查詢的ksy, 就訪問mysql), 直接繞過緩存, 訪問myslq, 而製造db的請求壓力;
解決: 將從mysql請求出的空存入redis一定時間;
問題二: 緩存擊穿
說明: 某一熱點key在高併發訪問的情況下, 突然失效, 導致大量的併發直接訪問mysql數據庫的情況;
解決1: 使用redis的分佈式suo解決mysql的訪問壓力問題;
問題三: 緩存雪崩
說明: 緩存時大量的key採用了相同的過期時間, 導致緩存存在某一時刻同時失效, 導致大量訪問db, db崩潰;
解決: 設置不同的失效時間;
測試代碼
@Override
public PmsSkuInfo getSkuById(String skuId) {
PmsSkuInfo pmsSkuInfo = new PmsSkuInfo();
//1.連接緩存
Jedis jedis = redisUtil.getJedis();
System.out.println("jedis:"+jedis);
//2.查看緩存
String skuKey = "sku:"+skuId + ":info";
String skuJson = jedis.get(skuKey);
//3.如果緩存中沒有, 則查看mysql中(緩存穿透, 雪崩)
if (StringUtil.isBlank(skuJson)){
SetParams params = new SetParams().nx().px(10000);
String OK = jedis.set("sku:"+skuId+":lock","1",params);
System.out.println("nx加鎖");
if (StringUtil.isBlank(OK) && OK.equals("OK")){
System.out.println("從mysql中獲取數據");
pmsSkuInfo = this.getSkuByIdFromDB(skuId);
//4.mysql查詢數據保存在redis中
if (pmsSkuInfo != null){
String json = JSON.toJSONString(pmsSkuInfo);
jedis.set(skuKey, json);
System.out.println("保存到redis");
}else{
//防止穿透
jedis.setex(skuKey,60*3,JSON.toJSONString(""));
}
//從數據庫獲取到數據之後,接觸鎖
jedis.decr("sku:"+skuId+":lock");
}else{
System.out.println("自旋:"+skuId);
//自旋
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return getSkuById(skuId);
}
}else{
pmsSkuInfo = JSON.parseObject(skuJson, PmsSkuInfo.class);
System.out.println("從redis獲取數據");
}
jedis.close();
return pmsSkuInfo;
}