1.1 商铺查询
根据商铺ID查询
从 redis 中查询商铺,如果没有就从数据库查询然后存入 reids
/**
* 查询单个店铺
* @param id 店铺ID
* @return
*/
@Override
public Result queryShopById(Long id) {
// 1.从 redis 中查询
String cacheShopJson = stringRedisTemplate.opsForValue().get(RedisConstants.CACHE_SHOP_KEY + id);
if(StrUtil.isNotBlank(cacheShopJson)) {
// 存在直接返回
return Result.ok(JSONUtil.toBean(cacheShopJson,Shop.class));
}
// 2.缓存没有的话从数据库查询
QueryWrapper<Shop> shopQueryWrapper = new QueryWrapper<>();
shopQueryWrapper.eq("id",id);
Shop shop = shopMapper.selectOne(shopQueryWrapper);
// 3.设置到 redis 里给后面做缓存用
stringRedisTemplate.opsForValue().
set(RedisConstants.CACHE_SHOP_KEY + id,
JSONUtil.toJsonStr(shop),
RedisConstants.CACHE_SHOP_TTL,
TimeUnit.MINUTES);
return Result.ok(shop);
}
1.2 商铺缓存与数据库的双写一致
两种方法
先更新数据库,删除缓存,写入缓存
先删除缓存,更新数据库,写入缓存
我们这里选用第一种
缓存命中直接返回,如果没有命中缓存就从数据库查询然后写入缓存
都存在着线程安全的问题
更新完之后会删除缓存,后续查询的时候就会没有命中缓存,然后就去数据库查询写入缓存
/**
* 先操作数据库在更新
* @param shop
* @return
*/
@Override
@Transactional
public Result update(Shop shop)
{
Long id = shop.getId();
if(id == null) { return Result.fail("店铺ID不能为空"); }
// 1.更新数据库
updateById(shop);
// 2.删除缓存
stringRedisTemplate.delete(RedisConstants.CACHE_SHOP_KEY + id);
return Result.ok();
}
}
1.3 缓存穿透
客户端请求的数据,缓存和数据库中都不存在
方案
缓存空对象
优点 : 实现简单,维护方便
缺点 : 额外的内存消耗
布隆过滤器
优点 : 内存占用少,没有多余的key
缺点 : 实现复杂.可能存在误判
1.3.1 实现缓存空对象
key - 前缀 + ID

文章介绍了如何使用Redis进行缓存查询,包括从Redis和数据库的查询顺序、缓存与数据库的双写一致性选择先更新数据库再删除缓存的方法、防止缓存穿透的空对象缓存策略、处理缓存雪崩的随机时间戳和集群方案以及应对缓存击穿的互斥锁和逻辑过期时间方法。此外,还提供了互斥锁的实现和测试方法。
最低0.47元/天 解锁文章
997

被折叠的 条评论
为什么被折叠?



