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

news2024/11/27 10:14:01

前景:

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

1.缓存更新策略

1.1.三种常见的更新策略

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

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

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

        

        

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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客户端查看,目前是有shop的缓存的:

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

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

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

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

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

        ​​​​​​​        ​​​​​​​        

这就保证了当数据库更新时,会立即删除redis中的缓存,实现双写一致。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1620634.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

mysql索引最左匹配原则的理解?(绝对牛逼)

前言 测试的时候就发现不对劲 CREATE TABLE student (id int(11) NOT NULL AUTO_INCREMENT,name varchar(255) DEFAULT NULL,cid int(11) DEFAULT NULL,PRIMARY KEY (id),KEY name_cid_INX (name,cid),KEY name_INX (name) ) ENGINEInnoDB AUTO_INCREMENT8 DEFAULT CHARSETut…

vue封装请求、合并js、合并多个js

vue封装请求、合并js、合并多个js 作为一个后端开发,写前端时发现,每次导入api接口都会有一堆代码,像下面这样: import {footprintList, footprintDelete} from /api/userApi.js import {addressList} from /api/userApi.js impor…

CPU资源控制

一、CPU资源控制定义 cgroups(control groups)是一个非常强大的linux内核工具,他不仅可以限制被namespace隔离起来的资源, 还可以为资源设置权重、计算使用量、操控进程启停等等。 所以cgroups(control groups&#xf…

西圣、小米、倍思开放式耳机好用吗?详细测评对比性能王者

身为一名在数码科技领域有着丰富经验的测评师,我深入接触过各种开放式耳机。在众多开放式耳机品牌中,西圣、小米和倍思三款产品以其出色的性能和独特的设计,受到市场的广泛议论,今天我将为大家带来这三款开放式耳机的详细测评对比…

最新AI创作系统ChatGPT网站源码Midjourney-AI绘画系统,Suno-v3-AI音乐生成大模型。

一、前言 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统,支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美,那么如何搭建部署AI创作ChatGPT?小编这里写一个详细图文教程吧。已支持GPT…

Laravel 6 - 第十二章 控制器

​ 文章目录 Laravel 6 - 第一章 简介 Laravel 6 - 第二章 项目搭建 Laravel 6 - 第三章 文件夹结构 Laravel 6 - 第四章 生命周期 Laravel 6 - 第五章 控制反转和依赖注入 Laravel 6 - 第六章 服务容器 Laravel 6 - 第七章 服务提供者 Laravel 6 - 第八章 门面 Laravel 6 - …

javaScript基础3

javaScript 一.对象1.概念2.创建对象的三种方法(1).字面量创建(利用{})(2)变量、属性、函数、方法的区别(3).new Object创建(4).构造函数 3.new关键字的执行过程4.遍历对象(for..in) 二.内置对象1.了解2.math对象3.日期对象(构造函…

挖矿木马基础知识

文章目录 一、概述二、挖矿介绍三、挖矿的收益四、挖矿木马的传播方式漏洞利用NSA武器的使用无文件挖矿利用网页挂马暴力挖矿病毒黑吃黑 五、防范建议六、学习参考 一、概述 比特币(Bitcoin)的概念最初由中本聪在 2008年11月1日提出,并于 2009年1月3日正式诞生。根…

Shell全套课程2小时速通从小白变高手

1.Shell概述 1.1为什么要学shell ​ 1.看懂运维人员编写的shell脚本 ​ 2.偶尔会编写一些简单的shell程序来管理集群,提高开发效率 1.2 Shell介于外层应用和LInux内核之间;用来操作Linux内核; Shell是一个命令行解释器,它接收…

算法课程笔记——如何进制转换

python特性 八、为什么负数的补码的求法是反码1 因为负数的反码加上这个负数的绝对值正好等于1111,在加1,就是10000,也就是四位二进数的模,而负数的补码是它的绝对值的同余数,可以通过模减去负数的绝对值得到它的补码&…

2024最新SSL证书在线申请系统源码 | 支持API接口 支持在线付费 二开优化版

内容目录 一、详细介绍二、效果展示1.部分代码2.效果图展示 三、学习资料下载 一、详细介绍 2024最新SSL证书在线申请系统源码 | 支持API接口 支持在线付费 二开优化版 最新SSL证书在线申请系统源码 | 支持API接口 SSL证书保证网络安全的基本保障。向您介绍我们的在线生成SSL…

权威解析Spring框架九大核心功能(续篇):专业深度,不容错过

作者介绍:✌️大厂全栈码农|毕设实战开发,专注于大学生项目实战开发、讲解和毕业答疑辅导。 推荐订阅精彩专栏 👇🏻 避免错过下次更新 Springboot项目精选实战案例 更多项目:CSDN主页YAML墨韵 学如逆水行舟&#xff0c…

速度与激情:超高速--100G网卡篇

在数字化时代,信息传输的速度和效率成为了各个领域的关键。在这个快节奏的世界里,网络连接的快慢直接影响着工作效率、生活质量甚至是创新能力。而在网络连接技术中,网卡的作用举足轻重。近年来,随着网络技术的不断发展&#xff0…

路由引入,路由过滤,路由策略简单实验

实验要求: 1、按照图示配置 IP 地址,R1,R3,R4 上使用 1oopback 口模拟业务网段 2、R1 和 R2 运行 RIPv2,R2,R3和R4 运行 OSPF,各自协议内部互通 3、在 RIP 和 OSPF 间配置双向路由引入&#x…

在PostgreSQL中,如何创建一个触发器并在特定事件发生时执行自定义操作?

文章目录 解决方案示例代码1. 创建自定义函数2. 创建触发器 解释 在PostgreSQL中,触发器(trigger)是一种数据库对象,它能在特定的事件(如INSERT、UPDATE或DELETE)发生时自动执行一系列的操作。这些操作可以…

短期斩获多个访问学者邀请函|高校教师获批CSC赴伦敦大学学院

B老师申报的是2023年CSC西部/地方合作项目,因申报在即,所以时间是第一要素,国家定位在英国及澳大利亚。经过努力,我们先后获得英国布里斯托大学、伦敦大学学院及澳大利亚昆士兰大学等多个邀请函,最终其选择了英国伦敦大…

CSS学习(选择器、盒子模型)

1、CSS了解 CSS:层叠样式表,一种标记语言,用于给HTML结构设置样式。 样式:文字大小、背景颜色等 p标签内不能嵌套标题标签。 2、CSS编写位置 1、行内样式(内联样式):在标签里添加样式&#…

谷歌搜索SEO优化需要做什么?

最基本的要求,网站基础要优化好,让你的网站更加友好地服务于用户和搜索引擎,首先你要保证你的网站也适配手机端,现在手机端,如果你的网站在手机上打开慢,或者没有适配手机端,让用户用手机看着电…

Git merge的版本冲突实验

实验目的 发现 两个分支的 相同文件 怎样被修改 才会发生冲突? 实验过程 1.初始状态 现在目前有1.py、2.py两个文件,已经被git管理。现在我想制造冲突,看怎样的修改会发生冲突,先看怎么不会发生冲突。 目前仓库里的版本是这样…

【MySQL】A01、性能优化-参数监控分析

1、参数监控 1.1、MySQL command 查看 mysql>SHOW STATUS; (服务器状态变量,运行服务器的统计和状态指标) mysql> SHOW VARIABLES;(服务器系统变量,实际上使用的变量的值) mysql> SHOW STATUS …