黑马点评笔记 redis实现缓存

文章目录

  • 什么是缓存?
    • 为什么要使用缓存
  • 如何使用缓存
    • 功能实现
      • 缓存模型和思路
      • 代码实现
  • 缓存更新策略
    • 数据库缓存不一致解决方案
      • 代码实现

什么是缓存?

缓存(Cache),就是数据交换的缓冲区,俗称的缓存就是缓冲区内的数据,一般从数据库中获取,存储于本地代码(例如:

1:Static final ConcurrentHashMap<K,V> map = new ConcurrentHashMap<>(); 本地用于高并发例2:static final Cache<K,V> USER_CACHE = CacheBuilder.newBuilder().build(); 用于redis等缓存例3:Static final Map<K,V> map =  new HashMap(); 本地缓存

由于其被Static修饰,所以随着类的加载而被加载到内存之中,作为本地缓存,由于其又被final修饰,所以其引用(例3:map)和对象(例3:new HashMap())之间的关系是固定的,不能改变,因此不用担心赋值(=)导致缓存失效;

为什么要使用缓存

缓存数据存储于代码中,而代码运行在内存中,内存的读写性能远高于磁盘,缓存可以大大降低用户访问并发量带来的服务器读写压力。

实际开发过程中,企业的数据量,少则几十万,多则几千万,这么大数据量,如果没有缓存来作为"避震器",系统是几乎撑不住的,所以企业会大量运用到缓存技术;
但是缓存也会增加代码复杂度和运营的成本:
在这里插入图片描述

如何使用缓存

实际开发中,会构筑多级缓存来使系统运行速度进一步提升,例如:本地缓存与redis中的缓存并发使用

浏览器缓存:主要是存在于浏览器端的缓存

应用层缓存:可以分为tomcat本地缓存,比如之前提到的map,或者是使用redis作为缓存

数据库缓存:在数据库中有一片空间是 buffer pool,增改查数据都会先加载到mysql的缓存中

CPU缓存::当代计算机最大的问题是 cpu性能提升了,但内存读写速度没有跟上,所以为了适应当下的情况,增加了cpu的L1,L2,L3级的缓存

功能实现

缓存模型和思路

大体的思路是,把每次读取数据时,先从redis查询是否有数据,如果没有数据就从数据库中查询,然后把查询到的数据返回给前端,并且把数据写入redis。但是这个模型仍然存在一些问题,这些问题我们会在下面介绍。
在这里插入图片描述

代码实现

代码思路:如果缓存有,则直接返回,如果缓存不存在,则查询数据库,然后存入redis。

    @Overridepublic Result queryById(Long id) [String key = "cache:shop:" + 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) [return Result,fail("店铺不存在!");}// 6.存在,写AredisstringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop));// 7.返回return Result.ok(shop);
}

缓存更新策略

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

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

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

主动更新:我们可以手动调用方法把缓存删掉,通常用于解决缓存和数据库不一致问题
在这里插入图片描述

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

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

解决方案

  • Cache Aside Pattern 人工编码方式:缓存调用者在更新完数据库后再去更新缓存,也称之为双写方案
  • Read/Write Through Pattern : 由系统本身完成,数据库与缓存的问题交由系统本身去处理
  • Write Behind Caching Pattern :调用者只操作缓存,其他线程去异步处理数据库,实现最终一致

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

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

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

    • 更新缓存:每次更新数据库都更新缓存,无效写操作较多
    • 删除缓存:更新数据库时让缓存失效,查询时再更新缓存
  • 如何保证缓存与数据库的操作的同时成功或失败?

    • 单体系统,将缓存与数据库操作放在一个事务
    • 分布式系统,利用TCC等分布式事务方案

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

代码实现

我们首先要在业务代码里添加redis逻辑缓存的过期时间。

    @Overridepublic Result queryById(Long id) [String key = "cache:shop:" + 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) [return Result,fail("店铺不存在!");}// 6.存在,写redis,添加过期时间stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop), timeout: 30L,TimeUnit.MINUTES);// 7.返回return Result.ok(shop);
}

插入代码修改,当我们修改了数据之后,然后把缓存中的数据进行删除,查询时发现缓存中没有数据,则会从mysql中加载最新的数据,从而避免数据库和缓存不一致的问题

  @Overridepublic Result updateShop(Shop shop) {Long id = shop.getId();if(id==null){return Result.fail("店铺id不能为空");}updateById(shop);//添加的更新后删除的代码stringRedisTemplate.delete(CACHE_SHOP_KEY+id);return Result.ok();}

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

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

相关文章

vr小鼠虚拟解剖实验教学平台减少了受感染风险

家畜解剖实验教学是培养畜牧兽医专业学生实际操作能力的专业教学活动中的核心手段。采取新型教学方式与手段&#xff0c;合理设置实验教学内容&#xff0c;有助于激发学生的操作积极性&#xff0c;促进实践教学的改革。 家畜解剖VR仿真教学是一种借助VR虚拟现实制作和web3d开发…

常用通信接口、协议:SCCB

一、概述 SCCB(串行摄像头控制总线)是由欧姆尼图像技术公司&#xff08;OmniVision&#xff09;开发的一种类IIC的总线&#xff0c;主要用于其OV系列的图像传感器上&#xff08;但目前有很多家的图像传感器都有采用该控制总线&#xff09;。相对于IIC总线来说SCCB与之最主要的差…

java基础-集合

1、集合 在java中&#xff0c;集合&#xff08;Collection&#xff09;指的是一组数据容器&#xff0c;它可以存储多个对象&#xff0c;并且允许用户通过一些方法来访问与操作这些对象。j 集合的实现原理都基于数据结构和算法&#xff0c;如下&#xff1a; 数据结构&#xff1…

振南技术干货集:制冷设备大型IoT监测项目研发纪实(2)

注解目录 1.制冷设备的监测迫在眉睫 1.1 冷食的利润贡献 1.2 冷设监测系统的困难 &#xff08;制冷设备对于便利店为何如何重要&#xff1f;了解一下你所不知道的便利店和新零售行业。关于电力线载波通信的论战。&#xff09; 2、电路设计 2.1 防护电路 2.1.1 强电防护 …

基于JavaWeb+SSM+Vue教学辅助微信小程序系统的设计和实现

基于JavaWebSSMVue教学辅助微信小程序系统的设计和实现 源码获取入口前言主要技术系统设计功能截图Lun文目录订阅经典源码专栏Java项目精品实战案例《500套》 源码获取 源码获取入口 前言 1.1 概述 随着信息时代的快速发展&#xff0c;互联网的优势和普及&#xff0c;人们生活…

[项目管理-33/创业之路-87/管理者与领导者-127]:如何提升自己项目管理的能力和水平

目录 前言&#xff1a; 一、项目经理的角色定位 1.1 项目经理的职责 1.2 不同矩阵类型的项目&#xff0c;项目经理的职责 1.3 项目经理的角色定位 1.4 项目经理的发展路径 二、项目经理项目理论和知识结构 三、软件项目经理在计算机水平的提升 四、项目经理业务知识的…

nodejs微信小程序+python+PHP-储能电站运营管理系统的设计与实现-计算机毕业设计推荐

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

七、通过libfdk_aac编解码器实现aac音频和pcm的编解码

前言 测试环境&#xff1a; ffmpeg的4.3.2自行编译版本windows环境qt5.12 AAC编码是MP3格式的后继产品&#xff0c;通常在相同的比特率下可以获得比MP3更高的声音质量&#xff0c;是iPhone、iPod、iPad、iTunes的标准音频格式。 AAC相较于MP3的改进包含&#xff1a; 更多的采…

系列八、key是弱引用,gc垃圾回收时会影响ThreadLocal正常工作吗

一、key是弱引用&#xff0c;gc垃圾回收时会影响ThreadLocal正常工作吗 到这里&#xff0c;有些小伙伴可能有疑问&#xff0c;ThreadLocalMap的key既然是 弱引用&#xff0c;那么GC时会不会贸然地把key回收掉&#xff0c;进而影响ThreadLocal的正常使用呢&#xff1f;答案是不会…

HTML新手入门笔记整理:HTML基本标签

结构标签 <html> </html> 告诉浏览器这个页面是从<html> 开始&#xff0c;到 </html>结束 <head> </head> 网页的头部&#xff0c;用于定义一些特殊内容&#xff0c;如页面标题、定时刷新、外部文件等。 <body> </body> …

基于SSM的旅游管理系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

数据分析基础之《matplotlib(1)—介绍》

一、什么是matplotlib 1、专门用于开发2D图表&#xff08;包括3D图表&#xff09; 2、使用起来及其简单 3、以渐进、交互方式实现数据可视化 4、matplotlib mat&#xff1a;matrix&#xff08;矩阵&#xff09; plot&#xff1a;画图 lib&#xff1a;库 二、为什么要学习m…

记录一次因内存不足而导致hiveserver2和namenode进程宕机的排查

背景 最近发现集群主节点总有进程宕机&#xff0c;定位了大半天才找到原因&#xff0c;分享一下 排查过程 查询hiveserver2和namenode日志&#xff0c;都是正常的&#xff0c;突然日志就不记录了&#xff0c;直到我重启之后又恢复工作了。 排查各种日志都是正常的&#xff0…

代码规范之-理解ESLint、Prettier、EditorConfig

前言 团队多人协同开发项目&#xff0c;困扰团队管理的一个很大的问题就是&#xff1a;无可避免地会出现每个开发者编码习惯不同、代码风格迥异&#xff0c;为了代码高可用、可维护性&#xff0c;需要从项目管理上尽量统一和规范代码。理想的方式需要在项目工程化方面&#xff…

部署jekins遇到的问题

jdk问题 我用的jdk版本是21的结果版本太新了&#xff0c;启动jekins服务的时候总是报错最后在jekins的安装目录下面的jekinsErr.log查看日志发现是jdk问题最后换了一个17版本的就解决了。 unity和jekins jekins和Git源码管理 jekins和Git联动使用 我想让jekins每次打包的时…

3D电路板在线渲染案例

从概念上讲,这是有道理的,因为PCB印制电路板上的走线从一个连接到下一个连接的路线基本上是平面的。 然而,我们生活在一个 3 维世界中,能够以这种方式可视化电路以及相应的组件,对于设计过程很有帮助。本文将介绍KiCad中基本的3D查看功能,以及如何使用NSDT 3DConvert在线…

Day38力扣打卡

打卡记录 网格中的最小路径代价&#xff08;动态规划&#xff09; 链接 class Solution:def minPathCost(self, grid: List[List[int]], moveCost: List[List[int]]) -> int:m, n len(grid), len(grid[0])f [[0x3f3f3f3f3f] * n for _ in range(m)]f[0] grid[0]for i i…

Sentinel 授权规则 (AuthorityRule)

Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件&#xff0c;主要以流量为切入点&#xff0c;从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。 SpringbootDubboNacos 集成 Sentinel&…

Unity 三维场景的搭建 软件构造实验报告

实验2&#xff1a;仿真系统功能实现 1.实验目的 &#xff08;1&#xff09;熟悉在Unity中设置仿真场景&#xff1b; &#xff08;2&#xff09;熟悉在Unity中C#语言的使用&#xff1b; &#xff08;3&#xff09;熟悉仿真功能的实现。 2.实验内容 新建一个仿真场景&#x…

SpringBoot_websocket实战

SpringBoot_websocket实战 前言1.websocket入门1.1 websocket最小化配置1.1.1 后端配置1.1.2 前端配置 1.2 websocket使用sockjs1.2.1 后端配置1.2.2 前端配置 1.3 websocket使用stomp协议1.3.1 后端配置1.3.2 前端配置 2.websocket进阶2.1 websocket与stomp有什么区别2.2 webs…