给查询业务添加redis缓存和缓存更新策略

目录

一、添加redis缓存的主要逻辑

二、代码

三、结果

四、缓存更新策略

五、代码


一、添加redis缓存的主要逻辑

在未添加缓存时,前端向后端发起查询请求时,后端收到请求就直接查数据库,它的速度如下:

其实速度也不慢,那是因为我的数据库里面没有太多数据,所以查起来速度还是特别快的,但随着我们的数据库数据量逐渐增大,如果没有缓存的话,那查询速度会越来越慢。

添加redis缓存的逻辑也不难,总结下来也就是以下这几点:

1.后端查询时,先查redis缓存,redis缓存中有数据直接返回,没有数据再去查数据库

2.查数据库时,没有对应数据则向前端发出错误信息,有数据则向前端发送数据并将数据写入redis缓存中

流程图如下所示:

二、代码

java 复制代码
@Service
public class ShopServiceImpl extends ServiceImpl<ShopMapper, Shop> implements IShopService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    /**
     * 根据id查询店铺信息
     * @param id
     * @return
     */
    @Override
    public Result queryById(Long id) {
        String key = RedisConstants.CACHE_SHOP_KEY + id;
        //1.从redis中查询商铺缓存信息
        String shopJson = stringRedisTemplate.opsForValue().get(key);
        //2、判断是否存在
        if (StrUtil.isNotBlank(shopJson)) {
            //3、存在,直接返回
            Shop shop = JSONUtil.toBean(shopJson, Shop.class);
            return Result.ok(shop);
        }
        //4、不存在,根据id查询数据库
        Shop shop = getById(id);
        //5、判断数据库中是否有数据
        if (shop == null) {
            //6、没有,返回错误
            return Result.fail("店铺不存在");
        }
        //7、有数据,返回,并将数据写入redis
        String jsonStr = JSONUtil.toJsonStr(shop);
        stringRedisTemplate.opsForValue().set(key,jsonStr);
        //8、返回结果
        return Result.ok(shop);
    }
}

三、结果

当第一次执行时,redis中是没有数据的,执行过后就会将对应数据写入redis中

下一次的查询时速度就会快上不少

如果数据库中的数据更多的话,效果会更加明显

四、缓存更新策略

既然我们已经对查询业务增加了缓存,那当数据库的数据和缓存数据不一样的时候,我们如何去解决它们之间的一致性问题呢?

其实解决方案十分简单:

当数据库的数据发生变更时,例如增加、删除、修改等操作,我们先去操作数据库再去删除缓存。

为什么选择删除缓存而不选择更新缓存呢?

如果选择更新缓存很可能会出现多次无效的写操作,比如:我更新了十次数据库之后才有一次查询操作,这时候缓存也是随之更新了十次。那如果我在他第一次更新数据库的时候就选择删除缓存,那么我就省去了这些更新缓存的无效写操作,性能上肯定是提高了不少。因此我们会选择删除缓存而不是更新缓存。

为什么要选择先操作数据库而不是先操作缓存呢?

因为数据库是基于磁盘的,缓存是基于内存的,操作数据库的耗时往往会比操作缓存的耗时大上不少。因此如果先删缓存再更新数据库,那就会出现在更新数据库的过程中(时间比较长)被其他查询缓存的操作乘虚而入,这时候缓存为空会从数据库中拿数据填入缓存,这时候就会出现数据不一致的问题。因此我们会选择先操作数据库再操作缓存。

因此我们还要给上面写的代码进行补全,在对数据进行修改的时候要进行以下的逻辑:

1.更新数据库

2.删除缓存

五、代码

java 复制代码
    @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);
        //3.返回结果
        return Result.ok();
    }
相关推荐
数据智能老司机6 分钟前
CockroachDB权威指南——SQL调优
数据库·分布式·架构
数据智能老司机7 分钟前
CockroachDB权威指南——应用设计与实现
数据库·分布式·架构
XuanXu10 分钟前
Java AQS原理以及应用
java
数据智能老司机20 分钟前
CockroachDB权威指南——CockroachDB 模式设计
数据库·分布式·架构
风象南3 小时前
SpringBoot中6种自定义starter开发方法
java·spring boot·后端
mghio12 小时前
Dubbo 中的集群容错
java·微服务·dubbo
咖啡教室17 小时前
java日常开发笔记和开发问题记录
java
咖啡教室17 小时前
java练习项目记录笔记
java
鱼樱前端17 小时前
maven的基础安装和使用--mac/window版本
java·后端