给查询业务添加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();
    }
相关推荐
白宇横流学长4 分钟前
基于SpringBoot实现的校园失物招领平台设计与实现【源码+文档】
java·spring boot·后端
罗超驿7 分钟前
6.Java多线程详解:Thread类、线程属性与start()方法深度解析
java·开发语言·面试·java-ee
一只fish11 分钟前
Oracle官方文档翻译《Database Concepts 26ai》第14章-物理存储结构
数据库·oracle
苦逼的猿宝14 分钟前
IT技术交流和分享平台的设计与实现(源码+论文)
java·毕业设计·springboot·计算机毕业设计
摇滚侠17 分钟前
IDEA 需要修改的配置 开发工具
java·ide·intellij-idea
2601_9577867722 分钟前
企业矩阵运营的“三段论“:管号、产内容、获线索——全链路系统的价值拆解
java·前端·矩阵·多平台管理
hhb_61823 分钟前
GraphQL实战避坑指南:性能与安全优化
数据库·安全·graphql
Run_Teenage24 分钟前
算法模板:输入输出,并查集
java·开发语言·算法
一 乐28 分钟前
公交线路查询系统|基于Java+vue公交线路查询系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·公交线路查询系统
AllData公司负责人31 分钟前
亲测丝滑,体验跃迁|AllData通过集成开源项目Datart,让数据可视化一目了然
java·大数据·数据库·python·数据可视化·数据视图·datart