Redis使用

环境配置 

 

 

 

代码实现

Java
public CoursePublish getCoursePublishCache(Long courseId){//查询缓存Object  jsonObj = redisTemplate.opsForValue().get("course:" + courseId);if(jsonObj!=null){String jsonString = jsonObj.toString();System.out.println("=================从缓存查=================");CoursePublish coursePublish = JSON.parseObject(jsonString, CoursePublish.class);return coursePublish;} else {System.out.println("从数据库查询...");//从数据库查询CoursePublish coursePublish = getCoursePublish(courseId);if(coursePublish!=null){redisTemplate.opsForValue().set("course:" + courseId, JSON.toJSONString(coursePublish));}return coursePublish;}
}
}

 缓存穿透问题

大量并发去访问一个数据库不存在的数据,由于缓存中没有该数据导致大量并发查询数据库,这个现象要缓存穿透。

如何解决缓存穿透?

1、对请求增加校验机制

比如:课程Id是长整型,如果发来的不是长整型则直接返回。

2、使用布隆过滤器

什么是布隆过滤器,以下摘自百度百科:

布隆过滤器可以用于检索一个元素是否在一个集合中。如果想要判断一个元素是不是在一个集合里,一般想到的是将所有元素保存起来,然后通过比较确定。链表,树等等数据结构都是这种思路. 但是随着集合中元素的增加,我们需要的存储空间越来越大,检索速度也越来越慢(O(n),O(logn))。不过世界上还有一种叫作散列表(又叫哈希表,Hash table)的数据结构。它可以通过一个Hash函数将一个元素映射成一个位阵列(Bit array)中的一个点。这样一来,我们只要看看这个点是不是1就可以知道集合中有没有它了。这就是布隆过滤器的基本思想。

布隆过滤器的特点是,高效地插入和查询,占用空间少;查询结果有不确定性,如果查询结果是存在则元素不一定存在,如果不存在则一定不存在;另外它只能添加元素不能删除元素,因为删除元素会增加误判率。

比如:将商品id写入布隆过滤器,如果分3次hash此时在布隆过滤器有3个点,当从布隆过滤器查询该商品id,通过hash找到了该商品id在过滤器中的点,此时返回1,如果找不到一定会返回0。

所以,为了避免缓存穿透我们需要缓存预热将要查询的课程或商品信息的id提前存入布隆过滤器,添加数据时将信息的id也存入过滤器,当去查询一个数据时先在布隆过滤器中找一下如果没有到到就说明不存在,此时直接返回。

实现方法有:

Google工具包Guava实现。

redisson 。

3、缓存空值或特殊值

请求通过了第一步的校验,查询数据库得到的数据不存在,此时我们仍然去缓存数据,缓存一个空值或一个特殊值的数据。

但是要注意:如果缓存了空值或特殊值要设置一个短暂的过期时间。

Java
public CoursePublish getCoursePublishCache(Long courseId) {//查询缓存Object  jsonObj = redisTemplate.opsForValue().get("course:" + courseId);if(jsonObj!=null){String jsonString = jsonObj.toString();if(jsonString.equals("null"))return null;CoursePublish coursePublish = JSON.parseObject(jsonString, CoursePublish.class);return coursePublish;} else {//从数据库查询System.out.println("从数据库查询数据...");CoursePublish coursePublish = getCoursePublish(courseId);//设置过期时间300秒redisTemplate.opsForValue().set("course:" + courseId, JSON.toJSONString(coursePublish),30, TimeUnit.SECONDS);return coursePublish;}
}

缓存雪崩问题

缓存雪崩是缓存中大量key失效后当高并发到来时导致大量请求到数据库,瞬间耗尽数据库资源,导致数据库无法使用。

造成缓存雪崩问题的原因是是大量key拥有了相同的过期时间,比如对课程信息设置缓存过期时间为10分钟,在大量请求同时查询大量的课程信息时,此时就会有大量的课程存在相同的过期时间,一旦失效将同时失效,造成雪崩问题。

 

 

3、缓存预热

不用等到请求到来再去查询数据库存入缓存,可以提前将数据存入缓存。使用缓存预热机制通常有专门的后台程序去将数据库的数据同步到缓存。

 

缓存击穿问题

缓存击穿是指大量并发访问同一个热点数据,当热点数据失效后同时去请求数据库,瞬间耗尽数据库资源,导致数据库无法使用。

比如某手机新品发布,当缓存失效时有大量并发到来导致同时去访问数据库。

1、使用同步锁控制查询数据库的线程

使用同步锁控制查询数据库的代码,只允许有一个线程去查询数据库,查询得到数据库存入缓存。

 

Java
public  CoursePublish getCoursePublishCache(Long courseId){//查询缓存Object  jsonObj = redisTemplate.opsForValue().get("course:" + courseId);if(jsonObj!=null){String jsonString = jsonObj.toString();CoursePublish coursePublish = JSON.parseObject(jsonString, CoursePublish.class);return coursePublish;}else{synchronized(this){Object  jsonObj = redisTemplate.opsForValue().get("course:" + courseId);if(jsonObj!=null){String jsonString = jsonObj.toString();CoursePublish coursePublish = JSON.parseObject(jsonString, CoursePublish.class);return coursePublish;}System.out.println("=========从数据库查询==========");//从数据库查询CoursePublish coursePublish = getCoursePublish(courseId);//设置过期时间300秒redisTemplate.opsForValue().set("course:" + courseId, JSON.toJSONString(coursePublish),300, TimeUnit.SECONDS);return coursePublish;}}}

2、热点数据不过期

可以由后台程序提前将热点数据加入缓存,缓存过期时间不过期,由后台程序做好缓存同步。

分布式锁 

上边的程序使用了同步锁解决了缓存击穿、缓存雪崩的问题,保证同一个key过期后只会查询一次数据库。

如果将同步锁的程序分布式部署在多个虚拟机上则无法保证同一个key只会查询一次数据库,如下图:

实现分布式锁的方案有很多,常用的如下:

1、基于数据库实现分布锁

利用数据库主键唯一性的特点,或利用数据库唯一索引的特点,多个线程同时去插入相同的记录,谁插入成功谁就抢到锁。

2、基于redis实现锁

redis提供了分布式锁的实现方案,比如:SETNX、set nx、redisson等。

拿SETNX举例说明,SETNX命令的工作过程是去set一个不存在的key,多个线程去设置同一个key只会有一个线程设置成功,设置成功的的线程拿到锁。

3、使用zookeeper实现

zookeeper是一个分布式协调服务,主要解决分布式程序之间的同步的问题。zookeeper的结构类似的文件目录,多线程向zookeeper创建一个子目录(节点)只会有一个创建成功,利用此特点可以实现分布式锁,谁创建该结点成功谁就获得锁。

 

  

Redisson

 

  • 加锁机制

线程去获取锁,获取成功: 执行lua脚本,保存数据到redis数据库。

线程去获取锁,获取失败: 一直通过while循环尝试获取锁,获取成功后,执行lua脚本,保存数据到redis

  • WatchDog自动延期看门狗机制

第一种情况:在一个分布式环境下,假如一个线程获得锁后,突然服务器宕机了,那么这个时候在一定时间后这个锁会自动释放,你也可以设置锁的有效时间(当不设置默认30秒时),这样的目的主要是防止死锁的发生

第二种情况:线程A业务还没有执行完,时间就过了,线程A 还想持有锁的话,就会启动一个watch dog后台线程,不断的延长锁key的生存时间。

  • lua脚本-保证原子性操作

主要是如果你的业务逻辑复杂的话,通过封装在lua脚本中发送给redis,而且redis是单线程的,这样就保证这段复杂业务逻辑执行的原子性

具体使用RLock操作分布锁,RLock继承JDK的Lock接口,所以他有Lock接口的所有特性,比如lock、unlock、trylock等特性,同时它还有很多新特性:强制锁释放,带有效期的锁,。

Java
//Redisson分布式锁
public  CoursePublish getCoursePublishCache(Long courseId){//查询缓存String jsonString = (String) redisTemplate.opsForValue().get("course:" + courseId);if(StringUtils.isNotEmpty(jsonString)){if(jsonString.equals("null")){return null;}CoursePublish coursePublish = JSON.parseObject(jsonString, CoursePublish.class);return coursePublish;}else{//每门课程设置一个锁RLock lock = redissonClient.getLock("coursequerylock:"+courseId);//获取锁lock.lock();try {jsonString = (String) redisTemplate.opsForValue().get("course:" + courseId);if(StringUtils.isNotEmpty(jsonString)){CoursePublish coursePublish = JSON.parseObject(jsonString, CoursePublish.class);return coursePublish;}System.out.println("=========从数据库查询==========");//从数据库查询CoursePublish coursePublish = getCoursePublish(courseId);redisTemplate.opsForValue().set("course:" + courseId, JSON.toJSONString(coursePublish),1,TimeUnit.DAYS);return coursePublish;}finally {//释放锁lock.unlock();}}}

 

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

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

相关文章

Redis之stream类型解读

目录 基本介绍 数据结构 消息 消费组 消费者 基本使用命令 概述 xadd 命令 xtrim 命令 xdel 命令 xlen 命令 xrange 命令 xread 命令 xgroup 命令 xreadgroup 命令 xack 命令 基本介绍 Redis stream(流)是一种数据结构,其…

基于React实现无限滚动的日历详细教程,附源码【手写日历教程第二篇】

前言 最常见的日历大部分都是滚动去加载更多的月份,而不是让用户手动点击按钮切换日历月份。滚动加载的交互方式对于用户而言是更加丝滑和舒适的,没有明显的操作割裂感。 那么现在需要做一个这样的无限滚动的日历,前端开发者应该如何去思考…

maven下载不了仓库地址为https的依赖jar,配置参数忽略ssl安全检查

问题原因 私服使用的https地址,然后安全证书过期的或没有,使用maven命令时,可以添加以下参数,忽略安全检查 mvn -Dmaven.wagon.http.ssl.insecuretrue -Dmaven.wagon.http.ssl.allowalltrue -Dmaven.wagon.http.ssl.ignore.vali…

慕课网 Go工程师 第三周 package和gomodules章节

Go包的引入: 包名前面加匿名,只引入但不使用,如果对应包有init函数,会执行init函数(初始化操作) 包名前面加. 把这个包的结构体和方法导入当前包,慎用,你不知道当前包和被引入的包用…

数据库事务四大特性

事务的4大特性(ACID): 原子性(Atomicity): 事务是数据库的逻辑工作单位,它对数据库的修改要么全部执行,要么全部不执行。 一致性(Consistemcy): 事务前后,数据库的状态都满足所有的完…

基于YOLOV8模型的课堂场景下人脸目标检测系统(PyTorch+Pyside6+YOLOv8模型)

摘要:基于YOLOV8模型的课堂场景下人脸目标检测系统可用于日常生活中检测与定位课堂场景下人脸,利用深度学习算法可实现图片、视频、摄像头等方式的目标检测,另外本系统还支持图片、视频等格式的结果可视化与结果导出。本系统采用YOLOv8目标检…

PHP自己的框架cookie()使用(完善篇七)

1、PHP自己的框架cookie() 2、cookie类&#xff08;CookieBase.php&#xff09; <?php class CookieBase {/*** 设置cookie*/public static function set($name, $value, $expire 3600, $path , $domain , $secure false, $httponly false) {setcookie($name, $valu…

字节律动之*你太美, emm 其实是个字符画雪花视频-哈哈哈-将视频转成一张张字符画图片

效果 整体效果 局部图片放大效果 视频转换后带雪花特效,凑合看吧, 视频地址 准备工作 安装FFmpeg 电脑上安装ffpeg处理视频并设置环境变量, windows可以参考FFmpeg的安装教程这篇博客安装 mac可以直接执行brew install ffmpeg安装 安装python依赖包 执行pip3 install -…

2023前端面试笔记 —— CSS3

系列文章目录 内容链接2023前端面试笔记HTML52023前端面试笔记CSS3 文章目录 系列文章目录前言一、CSS选择器的优先级二、通过 CSS 的哪些方式可以实现隐藏页面上的元素三、px、em、rem之间有什么区别&#xff1f;四、让元素水平居中的方法有哪些五、在 CSS 中有哪些定位方式六…

华为手机实用功能介绍

一、内置app介绍 分四块介绍&#xff0c;包括出门款、规划款、工作款和生活款。 出门款&#xff1a;红色框框部分&#xff0c;照镜子化妆/看天气 规划款&#xff1a;黄色框框部分&#xff0c;日程表/计划表/番茄时间/计时 工作款&#xff1a;蓝色框框部分&#xff0c;便笺/录…

基于android的学生公寓后勤系统/学生公寓管理系统APP

摘 要 随着网络科技的发展&#xff0c;移动智能终端逐渐走进人们的视线&#xff0c;相关应用越来越广泛&#xff0c;并在人们的日常生活中扮演着越来越重要的角色。因此&#xff0c;关键应用程序的开发成为影响移动智能终端普及的重要因素&#xff0c;设计并开发实用、方便的应…

快速排序笔记

一、quick_sort方法中如果 il,jr 会死循环的分析 1、示例代码 void quick_sort(int a[],int l,int r){if(l>r) return;int il,jr; //此处设置会导致死循环int x num[(lr)>>1];while(i<j){while(a[i] <x); //死循环的地方while(a[--j] >x);if(i<j) swap(a…

Docker consul的容器服务注册与发现

前言一、服务注册与发现二、consul 介绍三、consul 部署3.1 consul服务器3.1.1 建立 Consul 服务3.1.2 查看集群信息3.1.3 通过 http api 获取集群信息 3.2 registrator服务器3.2.1 安装 Gliderlabs/Registrator3.2.2 测试服务发现功能是否正常3.2.3 验证 http 和 nginx 服务是…

小研究 - JVM 的类装载机制

本文通过对一个类装载实例的分析&#xff0c;阐明了 Java虚拟机的类装载的代理机制和由此定义的命名空间&#xff0c;指出了类装载机制在容器/组件/抽象框架结构中的作用。 目录 1 引言 2 实例 3 分析 3.1 类装载的代理机制 3.2 Java的命名空间 3.3 解决问题 4 应…

VR智慧课堂 | 临床兽医学VR实验教学有哪些好处?

随着科技的不断发展&#xff0c;虚拟现实(VR)技术已经逐渐渗透到各个领域&#xff0c;为人们带来了前所未有的体验。在动物医学实验教学中&#xff0c;VR技术的应用也日益受到关注。本文将探讨临床兽医学VR实验教学的好处。 首先&#xff0c;VR技术能够提高动物医学实验的安全性…

江西萍乡能源石油化工阀门三维扫描3d测量抄数建模-CASAIM中科广电

长期以来&#xff0c;石油天然气、石油石化、发电和管道输送行业在环保、健康和安全保障方面一直承受着巨大的压力&#xff0c;他们必须确保相关规程在各项作业中得到全面贯彻。 阀门作为流体管道运输中的组成部分&#xff0c;其装配密封度是保证流体运输安全的重要一环&#…

数据结构初阶--排序

目录 一.排序的基本概念 1.1.什么是排序 1.2.排序算法的评价指标 1.3.排序的分类 二.插入排序 2.1.直接插入排序 2.2.希尔排序 三.选择排序 3.1.直接选择排序 3.2.堆排序 重建堆 建堆 排序 四.交换排序 4.1.冒泡排序 4.2.快速排序 快速排序的递归实现 法一&a…

查看windows当前占用的所有端口、根据ipt终止任务进程、OS、operatingSystem

文章目录 查询端口查询指定端口根据进程pid查询进程名称查看所有进程名称根据pid终止任务进程根据进程名称终止任务 查询端口 netstat -ano查询指定端口 netstat -ano | findstr "80"根据进程pid查询进程名称 tasklist | findstr "660"查看所有进程名称 ta…

0201hdfs集群部署-hadoop-大数据学习

文章目录 1 前言2 集群规划3 hadoop安装包上传与安装3.1 上传解压 4 hadoop配置5 从节点同步和环境变量配置6 创建用户7 集群启动8 问题集8.1 Invalid URI for NameNode address (check fs.defaultFS): file:/// has no authority. 结语 1 前言 下面我们配置下单namenode节点h…

arcgis:画一幅自己城市的shp地图

首先打开ArcGis10.6&#xff0c;点击带黄底的小加号&#xff0c;添加底图。 可以选择中国地图彩色版&#xff0c;然后双击&#xff0c;转动鼠标滑轮找到属于自己的城市。 点击-目录&#xff0c;在新建的文件夹里右击-新建-shapefile。 格式选择折线&#xff0c;先把主要河流道路…