【Redis】Redis实战:黑马点评之商户查询缓存

本文介绍了在Java项目中使用Redis实现商户查询缓存的全过程,包括添加商户和商户类型缓存、确保数据库与缓存双写一致性、解决缓存穿透和击穿问题。通过使用互斥锁和逻辑过期时间策略,有效避免了缓存问题,同时提供了封装的Redis工具类。
摘要由CSDN通过智能技术生成

Redis实战:黑马点评之商户查询缓存

关于缓存的知识点,我整合在了另一篇文章【Redis】Redis高级:缓存技术与缓存常见问题 之中,这里只解决项目中的代码编写问题,不再讲述有关缓存的知识点

1 添加商户缓存

在现有的代码中,查询商户信息是直接去数据库中进行查询的,由于商户信息是查询比较频繁的数据,因此我们可以为其添上缓存

在这里插入图片描述

那么添加缓存应该怎样进行编码呢?标准的操作方式就是查询数据库之前先查询缓存,如果缓存数据存在,则直接从缓存中返回,如果缓存数据不存在,再查询数据库,然后将数据存入redis。

在这里插入图片描述

具体实现代码如下:

@Service
public class ShopServiceImpl extends ServiceImpl<ShopMapper, Shop> implements IShopService {
   

    @Autowired
    private StringRedisTemplate  stringRedisTemplate;

    @Override
    public Result queryById(Long id) {
   
        //查询前先查询缓存
        //组装key
        String key = RedisConstants.CACHE_SHOP_KEY+id;

        //查询缓存信息是否存在
        String value = stringRedisTemplate.opsForValue().get(key);

        //缓存存在,直接返回缓存信息
        if(value != null){
   
            return Result.ok(JSONUtil.toBean(value,Shop.class));
        }

        //缓存不存在,则查询数据库信息
        Shop shop = getById(id);

        //数据库中也不存在则报错
        if(shop == null){
   
            return Result.fail("商户不存在");
        }

        //将查询出来的数据缓存在redis中
        stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop));

        //返回查询结果
        return Result.ok(shop);
    }

}

2 添加商户类型缓存

将商户类型查询的数据也添加进缓存

在这里插入图片描述

代码如下:

ShopTypeController

@RestController
@RequestMapping("/shop-type")
public class ShopTypeController {
   
    
    @Resource
    private IShopTypeService typeService;

    @GetMapping("list")
    public Result queryTypeList() {
   
        return typeService.queryTypeList();
    }
    
}

ShopTypeService

@Service
public class ShopTypeServiceImpl extends ServiceImpl<ShopTypeMapper, ShopType> implements IShopTypeService {
   

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public Result queryTypeList() {
   
        //先查询缓存
        String value = stringRedisTemplate.opsForValue().get("cache:shopType:list");

        //如果缓存不为空则直接返回
        if(value != null){
   
            return Result.ok(JSONUtil.toList(value,ShopType.class));
        }

        //缓存为空则查询数据库
        List<ShopType> shopTypeList = query().orderByAsc("sort").list();

        //将查询到的信息保存到缓存
        stringRedisTemplate.opsForValue().set("cache:shopType:list",JSONUtil.toJsonStr(shopTypeList));

        //响应数据
        return Result.ok(shopTypeList);
    }

}

3 实现数据库与缓存双写一致

为了确保缓存中的数据与数据库中数据的一致性,现修改有关于Shop的业务逻辑,满足下面的需求:

  • 需求一:根据id查询店铺时,如果缓存未命中,则查询数据库,将数据库结果写入缓存,并设置超时时间

  • 需求二:根据id修改店铺时,先修改数据库,再删除缓存

实现需求一:为缓存数据添加过期时间

修改ShopServiceImpl中的代码

@Service
public class ShopServiceImpl extends ServiceImpl<ShopMapper, Shop> implements IShopService {
   

    @Autowired
    private StringRedisTemplate  stringRedisTemplate;

    @Override
    public Result queryById(Long id) {
   
        //查询前先查询缓存
        //组装key
        String key = RedisConstants.CACHE_SHOP_KEY+id;

        //查询缓存信息是否存在
        String value = stringRedisTemplate.opsForValue().get(key);

        //缓存存在,直接返回缓存信息
        if(value != null){
   
            return Result.ok(JSONUtil.toBean(value,Shop.class));
        }

        //缓存不存在,则查询数据库信息
        Shop shop = getById(id);

        //数据库中也不存在则报错
        if(shop == null){
   
            return Result.fail("商户不存在");
        }

        //将查询出来的数据缓存在redis中
        stringRedisTemplate.opsForValue().set(
            key, 
            JSONUtil.toJsonStr(shop),
            RedisConstants.CACHE_SHOP_TTL, 
            TimeUnit.MINUTES
        );

        //返回查询结果
        return Result.ok(shop);
    }

}

实现需求二:当数据更新后,删除缓存数据

首先修改ShopController中的updateShop方法

    /**
     * 更新商铺信息
     * @param shop 商铺数据
     * @return 无
     */
    @PutMapping
    public Result updateShop(@RequestBody Shop shop) {
   
        // 写入数据库
        return shopService.updateShop(shop);
    }

然后在ShopServiceImpl中编写updateShop方法

   /**
     * 执行更新操作,更新后应该删除缓存
     * @param shop
     * @return
     */
    @Override
    @Transactional
    public Result updateShop(Shop shop) {
   
        Long shopId = shop.getId();
        if(shopId == null){
   
            return Result.fail("店铺id不能为空");
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值