Redis篇:缓存更新策略最佳实践

这篇具有很好参考价值的文章主要介绍了Redis篇:缓存更新策略最佳实践。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前景:

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

1.缓存更新策略

1.1.三种常见的更新策略

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

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

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

        Redis篇:缓存更新策略最佳实践,缓存,redis,数据库

        Redis篇:缓存更新策略最佳实践,缓存,redis,数据库

1.2.数据库缓存不一致的解决方案

        由于我们的缓存的数据源来自于数据库,而数据库的数据是会发生变化的,因此,如果当数据库中数据发生变化,而缓存却没有同步,此时就会有一致性问题存在,其后果是:

        用户使用缓存中的过时数据,就会产生类似多线程数据安全问题,从而影响业务,产品口碑等;怎么解决呢?有如下几种方案:

Cache Aside Pattern 人工编码方式:缓存调用者在更新完数据库后再去更新缓存,也称之为双写方案

Read/Write Through Pattern : 由系统本身完成,数据库与缓存的问题交由系统本身去处理

Write Behind Caching Pattern :调用者只操作缓存,其他线程去异步处理数据库,实现最终一致

1.3.数据一致性问题采用什么方案

综合考虑:使用方案一,但是方案一调用者如何处理呢?这里有几个问题

操作缓存和数据库时有三个问题需要考虑:

如果采用第一个方案,那么假设我们每次操作数据库后,都操作缓存,但是中间如果没有人查询,那么这个更新动作实际上只有最后一次生效,中间的更新动作意义并不大,我们可以把缓存删除,等待再次查询时,将缓存中的数据加载出来

  • 删除缓存还是更新缓存?

    • 更新缓存:每次更新数据库都更新缓存,无效写操作较多

    • 删除缓存:更新数据库时让缓存失效,查询时再更新缓存

  • 如何保证缓存与数据库的操作的同时成功或失败?

    • 单体系统,将缓存与数据库操作放在一个事务

    • 分布式系统,利用TCC等分布式事务方案

应该具体操作缓存还是操作数据库,我们应当是先操作数据库,再删除缓存,原因在于,如果你选择第一种方案,在两个线程并发来访问时,假设线程1先来,他先把缓存删了,此时线程2过来,他查询缓存数据并不存在,此时他写入缓存,当他写入缓存后,线程1再执行更新动作时,实际上写入的就是旧的数据,新的数据被旧数据覆盖了。

  • 先操作缓存还是先操作数据库?

    • 先删除缓存,再操作数据库

    • 先操作数据库,再删除缓存

Redis篇:缓存更新策略最佳实践,缓存,redis,数据库

因为更新数据库耗时比更新缓存耗时长很多,所以第二种情况发生的概率极低,比第一种低很多,所以综合考虑还是用第二种

2.实现缓存和数据库双写一致

比如我们把黑马点评项目拿来做示例:

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

核心思路:

 修改ShopController中的业务逻辑,满足下面的需求:

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

        2.根据id修改店铺时,先修改数据库,再删除缓存

先修改ShopServiceImpl中的queryById方法,设置一个过期时间:

/**
     * 根据id查询商铺
     * @param id
     * @return
     */
    @Override
    public Result queryById(Long id) {
        //1.从redis查询商铺缓存
        String key = RedisConstants.CACHE_SHOP_KEY + id;
        String shopJson = stringRedisTemplate.opsForValue().get(key);
        //2.判断是否存在
        if(StrUtil.isNotBlank(shopJson)){
            //3.存在,返回商铺信息
            Shop shop = JSONUtil.toBean(shopJson, Shop.class);
            return Result.ok(shop);
        }

        //4.不存在,去数据库查询
        Shop shop = getById(id);
        //5判断数据库中是否存在
        if(shop == null){
            //6.数据库中不存在,返回错误信息
            return Result.fail("店铺不存在!");
        }
        //7.数据库中存在,将商铺信息写入redis,返回商铺信息
        stringRedisTemplate.opsForValue().set(key,JSONUtil.toJsonStr(shop));
        //8.设置过期时间
        stringRedisTemplate.expire(key,RedisConstants.CACHE_SHOP_TTL, TimeUnit.MINUTES);
        return Result.ok(shop);
    }

再添加更新商铺时,需要进行删除缓存的操作:

        代码分析:通过之前的淘汰,我们确定了采用删除策略,来解决双写问题,当我们修改了数据之后,然后把缓存中的数据进行删除,查询时发现缓存中没有数据,则会从mysql中加载最新的数据,从而避免数据库和缓存不一致的问题。

ShopServiceImpl中的update方法:

 /**
     * 更新商铺信息
     * @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 +shop.getId());
        //返回
        return Result.ok();
    }

2.2. 测试

重启服务之后,先访问一下浏览器,访问商铺界面:

                ​​​​​​​        Redis篇:缓存更新策略最佳实践,缓存,redis,数据库

先去redis客户端查看,目前是有shop的缓存的:

Redis篇:缓存更新策略最佳实践,缓存,redis,数据库

接下来进行更新商铺操作,看看数据库发生改变的同时,是否会删除redis中缓存的shop:

我们使用postman发起更新请求:

Redis篇:缓存更新策略最佳实践,缓存,redis,数据库

发起请求之后,来到redis客户端:

Redis篇:缓存更新策略最佳实践,缓存,redis,数据库

可以看到,shop的缓存被删除了,说明没问题。

然后可以再去刷新一下浏览器,shop会重新添加缓存。

        ​​​​​​​        ​​​​​​​        Redis篇:缓存更新策略最佳实践,缓存,redis,数据库

Redis篇:缓存更新策略最佳实践,缓存,redis,数据库

这就保证了当数据库更新时,会立即删除redis中的缓存,实现双写一致。文章来源地址https://www.toymoban.com/news/detail-856849.html

到了这里,关于Redis篇:缓存更新策略最佳实践的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • springboot+redis+mysql+quartz-通过Java操作redis的KEYS*命令获取缓存数据定时更新数据库

    代码讲解: 3-点赞功能-定时持久化到数据库(pipeline+lua)-完善过程2_哔哩哔哩_bilibili https://www.bilibili.com/video/BV1w14y1o7BV 本文章代码: blogLike_schedule/like03 · xin麒/XinQiUtilsOrDemo - 码云 - 开源中国 (gitee.com) https://gitee.com/flowers-bloom-is-the-sea/XinQiUtilsOrDemo/tree/master/blogLike_schedule/like03 数据

    2024年02月15日
    浏览(52)
  • Redis缓存更新策略

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

    2023年04月26日
    浏览(37)
  • redis的缓存更新策略

    目录 三种缓存更新策略 业务场景:  主动更新的三种实现 操作缓存和数据库时有三个问题   1.删除缓存还是更新缓存?   2.如何保证缓存与数据库的操作的同时成功或失败?   3.先操作缓存还是先操作数据库? 缓存更新策略的最佳实践方案: 内存淘汰(Eviction)策略:Re

    2024年02月14日
    浏览(42)
  • Redis缓存更新策略以及常见缓存问题

    缓存就是数据交换的缓冲区(Cache),是存储数据的临时地方,一般读写性能较好,常见缓存: Web应用中缓存有什么作用呢? 降低后端负载 提高读写效率,降低响应时间 缓存的成本: 数据的一致性成本 代码维护成本 运维成本 缓存作用模型: 给一段Redis作为缓存的具体案例代

    2024年02月16日
    浏览(50)
  • redis 三种缓存更新策略

    今天聊聊redis 三种缓存更新策略分别是: Cache Aside(旁路缓存)策略; Read/Write Through(读穿 / 写穿)策略; Write Back(写回)策略; 其中 Cache Aside策略是redis和Mysql使用的更新策略,另外两种策略主要使用在计算机系统上。 Cache Aside(旁路缓存)策略是最常用的策略,应用程

    2024年02月15日
    浏览(39)
  • Redis实战(3)——缓存模型与缓存更新策略

    1 什么是缓存? 缓存 就是数据交换的缓冲区, 是存贮数据的临时区,一般读写性能较高 textcolor{red}{是存贮数据的临时区,一般读写性能较高} 是存贮数据的临时区,一般读写性能较高 。缓存可在多个场景下使用 以一次 w e b 请求为例,演示不同阶段的缓存作用 textcolor{blue}

    2024年02月15日
    浏览(42)
  • Redis实战案例4-缓存更新策略

    缓存中的数据一致性问题(数据库更新数据,而Redis存的是旧数据) 内存淘汰策略:当内存很充足时,很长时间无法淘汰数据,所以很难控制淘汰,一致性差; 超时剔除:取决于TTL大小,可以达到控制目的,但是在TTL时间内也可能存在数据库更新从而Redis中变成旧数据; 主动

    2024年02月10日
    浏览(43)
  • springboot+redis+mysql+quartz-使用pipeline+lua技术将缓存数据定时更新到数据库

    代码讲解:7.3点赞功能-定时持久化到数据库-Java程序整合pipeline+lua_哔哩哔哩_bilibili https://www.bilibili.com/video/BV1Lg4y1w7U9 代码: blogLike_schedule/like08 · xin麒/XinQiUtilsOrDemo - 码云 - 开源中国 (gitee.com) https://gitee.com/flowers-bloom-is-the-sea/XinQiUtilsOrDemo/tree/master/blogLike_schedule/like08 数据库表:

    2024年02月13日
    浏览(43)
  • 缓存解析:从架构设计到Redis应用及最佳实践

    在现代软件架构中,缓存是优化数据检索、提高应用性能的关键组件。缓存的存储位置多种多样,每个位置针对特定的优化目标和需求。理解这些层级对于设计高效的系统至关重要。 浏览器缓存 :这是最接近用户端的缓存层。浏览器缓存存储了用户经常访问的静态资源,如

    2024年01月22日
    浏览(48)
  • springboot+redis+mysql+quartz-通过Java操作jedis使用pipeline获取缓存数据定时更新数据库

    代码讲解:6-点赞功能-定时持久化到数据库-pipeline+lua-优化pipeline_哔哩哔哩_bilibili https://www.bilibili.com/video/BV1yP411C7dr 代码: blogLike_schedule/like06 · xin麒/XinQiUtilsOrDemo - 码云 - 开源中国 (gitee.com) https://gitee.com/flowers-bloom-is-the-sea/XinQiUtilsOrDemo/tree/master/blogLike_schedule/like06 数据库表的

    2024年02月16日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包