此处以行品详情为例,讲述如何解决高并发情况下如何解决缓存击穿问题,这里只是一种方法。
新建商品详情类ItemDo,此处为简易写法:
import java.io.Serializable;
import java.math.BigDecimal;
/**
* Description:商品详情,这里使用简易版
*
* @author Mr Li
* @date 2019/4/9
**/
@Setter
@Getter
@ToString
public class ItemDo implements Serializable {
/**
* 主键id
*/
private Long id;
/**
* 价格
*/
private BigDecimal price;
}
新建Cache类,重点在方法,代码如下:
/**
* 双层校验解决高并发情下缓存击穿问题
* @author Mr Li
* @date 2019/3/26
**/
public class Cache {
static Lock reenLock = new ReentrantLock();
private static final String KEY_PREFIX = "sku:";
private static final String KEY_SUFFIX = ":item";
public ItemDo getData(Long skuNum) throws InterruptedException {
// 从缓存读取数据
String skuKey = KEY_PREFIX + skuNum + KEY_SUFFIX;
ItemDo itemDo = getDataFromCache(skuKey);
//判断所得数据是否为null
if (itemDo == null) {
if (reenLock.tryLock()) {
try {
System.out.println("我拿到锁了,从DB获取数据库后写入缓存");
// 从数据库查询数据
itemDo = getDataFromDB(skuNum);
// 将查询到的数据写入缓存
setDataToCache(skuKey,itemDo);
} finally {
reenLock.unlock();// 释放锁
}
} else {
itemDo = getDataFromCache(skuKey);// 先查一下缓存
if (itemDo == null) {
System.out.println("我没拿到锁,缓存也没数据,先小憩一下");
Thread.sleep(200);// 睡一会儿
return getData(skuNum);// 重试
}
}
}
return itemDo;
}
//假设方法setDataToCache能将数据存入缓存,方法体略
private void setDataToCache(String itemKey,ItemDo itemDo) {
}
//假设方法getDataFromDB能从数据库中获得数据,参数与方法体略
private ItemDo getDataFromDB(Long skuNum) {
return null;
}
//假设方法getDataFromCache()能够获得缓存数据,方法体略
public ItemDo getDataFromCache(String skuKey){
return null;
}
}
如有错误,欢迎指正,谢谢。