dp商品缓存

缓存更新策略

缓存更新是redis为了节约内存而设计出来的一个东西,主要是因为内存数据宝贵,当我们向redis插入太多数据,此时就可能会导致缓存中的数据过多,所以redis会对部分数据进行更新,或者把他叫为淘汰更合适。

内存淘汰:redis自动进行,当redis内存达到咱们设定的max-memery的时候,会自动触发淘汰机制,淘汰掉一些不重要的数据(可以自己设置策略方式)

超时剔除:当我们给redis设置了过期时间ttl之后,redis会将超时的数据进行删除,方便咱们继续使用缓存

主动更新:我们可以手动调用方法把缓存删掉,通常用于解决缓存和数据库不一致问题

商品缓存代码:(String类型)

public Result queryById(Long id) {
// 1、提交店铺id
String key = CACHE_SHOP_KEY + id;
// 2、从redis查询店铺信息
String shopJson = stringRedisTemplate.opsForValue().get(key);
// 3.是否缓存命中
if(StrUtil.isNotBlank(shopJson)) {
    // 4. 命中直接返回
    Shop shop = JSONUtil.toBean(shopJson, Shop.class);
    return Result.ok(shop);
}
// 5、 未命中则根据id查询数据库
Shop shop = getById(id);
// 6、 判断商铺是否存在
if(shop == null) {
    // 不存在返回404
    return Result.fail("店铺不存在!");
}
// 7、 存在则存入redis
stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop));
// 8、返回
return Result.ok(shop);
}

商品类型缓存代码:(List类型)

public List<ShopType> queryTypeList() {
    // 1、构建key
    String key  = "cache:shopType:list";
    // 2、判断缓存是否命中
    List<String> shopTypeList = stringRedisTemplate.opsForList().range(key, 0, -1);
    List<ShopType> shopTypesByRedis = new ArrayList<>();
    if (shopTypeList != null && shopTypeList.size() > 0) {
        // 3、命中,将JSON数据转换成对象
        for (String shopType : shopTypeList) {
            ShopType type = JSONUtil.toBean(shopType, ShopType.class);
            shopTypesByRedis.add(type);
        }
        return shopTypesByRedis;
    }
    // 4、未命中,从数据库查询
    List<ShopType> shopTypeListMysql = query().orderByAsc("sort").list();
    // 5、将查询结果写入缓存
    if(shopTypeListMysql != null)  {
        for (ShopType shopType : shopTypeListMysql) {
            stringRedisTemplate.opsForList().rightPushAll(key, JSONUtil.toJsonStr(shopType));
        }
    } else {
        return null;
    }
    return shopTypeListMysql;
}

实现商铺和缓存与数据库双写一致

  • 根据id查询店铺时,如果缓存未命中,则查询数据库,将数据库结果写入缓存,并设置超时时间
// 7、 存在则存入redis
stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop), CACHE_SHOP_TTL, TimeUnit.MINUTES);
  • 根据id修改店铺时,先修改数据库,再删除缓存
public Result updateShop(Shop shop) {
Long id = shop.getId();
if(id == null) {
    return Result.fail("店铺id不能为空");
}
// 1. 更新数据库
updateById(shop);
// 2. 删除缓存
stringRedisTemplate.delete(CACHE_SHOP_KEY + id);
return Result.ok();
}

解决缓存穿透问题

if(StrUtil.isNotBlank(shopJson)) {
    // 4. 命中直接返回
    Shop shop = JSONUtil.toBean(shopJson, Shop.class);
    return Result.ok(shop);
}
// 是否为空值
if(shopJson.equals("")) {
    return Result.fail("店铺不存在!");
}
// 5、 未命中则根据id查询数据库
Shop shop = getById(id);
// 6、 判断商铺是否存在
if(shop == null) {
    // 将空值写入redis
    stringRedisTemplate.opsForValue().set(key,"", CACHE_NULL_TTL, TimeUnit.MINUTES);
    // 不存在返回404
    return Result.fail("店铺不存在!");
}

解决缓存击穿问题

常见的解决方案有两种:

  • 互斥锁
  • 逻辑过期

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值