比如现在才发布了iphone13,这人非要搜iphone100,这缓存没有,数据库也不可能有
public Map<String, List<Catelog2Vo>> getCatalogJson2() {
//给缓存中放json字符串,拿出的json字符串,反序列为能用的对象
/**
* 1、空结果缓存:解决缓存穿透问题
* 2、设置过期时间(加随机值):解决缓存雪崩
* 3、加锁:解决缓存击穿问题
*/
//1、加入缓存逻辑,缓存中存的数据是json字符串
//JSON跨语言。跨平台兼容。
ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
String catalogJson = ops.get("catalogJson");
if (StringUtils.isEmpty(catalogJson)) {
System.out.println("缓存不命中...查询数据库...");
//2、缓存中没有数据,查询数据库
Map<String, List<Catelog2Vo>> catalogJsonFromDb = getCatalogJsonFromDbWithRedissonLock();
//数据库查不到,把缓存设置为空
if(catalogJsonFromDb.isEmpty() || catalogJsonFromDb == null){
ops.set("catalogJson","0",300,TimeUnit.SECONDS);//设置一个标志位
}
return catalogJsonFromDb;
}
System.out.println("缓存命中...直接返回...");
//转为指定的对象
Map<String, List<Catelog2Vo>> result = JSON.parseObject(catalogJson,new TypeReference<Map<String, List<Catelog2Vo>>>(){});
return result;
}
具体业务代码
public Map<String, List<Catelog2Vo>> getCatalogJsonFromDbWithRedissonLock() {
//1、占分布式锁。去redis占坑
//(锁的粒度,越细越快:具体缓存的是某个数据,11号商品) product-11-lock
//RLock catalogJsonLock = redissonClient.getLock("catalogJson-lock");
//创建读锁
RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("catalogJson-lock");
RLock rLock = readWriteLock.readLock();
Map<String, List<Catelog2Vo>> dataFromDb = null;
try {
rLock.lock();
//加锁成功...执行业务 得到数据,在下面这个方法中把数据库得到的数据存入缓存
dataFromDb = getDataFromDb();
} finally {
rLock.unlock();
}
//先去redis查询下保证当前的锁是自己的
//获取值对比,对比成功删除=原子性 lua脚本解锁
// String lockValue = stringRedisTemplate.opsForValue().get("lock");
// if (uuid.equals(lockValue)) {
// //删除我自己的锁
// stringRedisTemplate.delete("lock");
// }
return dataFromDb;
}