目录
问题一: 缓存穿透
说明: 利用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;
}