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();}}}
相关文章:
Redis使用
环境配置 代码实现 Java public CoursePublish getCoursePublishCache(Long courseId){//查询缓存Object jsonObj redisTemplate.opsForValue().get("course:" courseId);if(jsonObj!null){String jsonString jsonObj.toString();System.out.println("从缓…...
#systemverilog# 之 event region 和 timeslot 仿真调度(七)Active/NBA 咋跳转的?
目录 一 目的 二 案例分析 2.1 先Active域,后 NBA 域 2.2 先Active域,后 NBA 域,后NBA域...
回归预测 | MATLAB实现SSA-ELM麻雀搜索算法优化极限学习机多输入单输出回归预测(多指标,多图)
回归预测 | MATLAB实现SSA-ELM麻雀搜索算法优化极限学习机多输入单输出回归预测(多指标,多图) 目录 回归预测 | MATLAB实现SSA-ELM麻雀搜索算法优化极限学习机多输入单输出回归预测(多指标,多图)效果一览基…...
LION AI 大模型落地,首搭星纪元 ES
自新能源汽车蓬勃发展以来,随着潮流不断进步和变革的“四大件”有着明显变化。其中有:平台、智能驾驶、配置、以及车机。方方面面都有着不同程度的革新。 而车机方面,从以前老旧的媒体机、 CD 机发展至如今具有拓展性、开放性、智能化的车机…...
【AC-自动机】- 字符串的逆序
链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网 题号:NC14310 时间限制:C/C 1秒,其他语言2秒 空间限制:C/C 32768K,其他语言65536K 64bit IO Format: %lld 题目描述 输入一个字符串…...
统计Mysql库中每个表的总行数,解决table_rows不准确问题
1、拼接SQL selectsubstring( GROUP_CONCAT(a.sf SEPARATOR ),1,length(GROUP_CONCAT(a.sf SEPARATOR ))-10) as sql_str from( select concat(select ", TABLE_name , ", count(*) as row_num from , TABLE_SCHEMA, .,TABLE_name, union all ) as sf frominformat…...
AWS EC2 docker-compose部署MongoDB4.2
环境准备 安装docker 参考EC2官方文档:创建容器镜像以在 Amazon ECS 上使用 - Amazon Elastic Container Service sudo yum update -y sudo amazon-linux-extras install docker sudo usermod -a -G docker ec2-user sudo systemctl enable docker sudo systemct…...
IDEA常用插件之类Jar包搜索Maven Search
文章目录 IDEA常用插件之类Jar包搜索Maven Search说明安装插件使用方法1.搜索自己要搜的jar包2.根据类名搜索 IDEA常用插件之类Jar包搜索Maven Search 说明 它可以帮助用户快速查找和浏览Maven中央存储库中可用的依赖项和插件。它可以帮助用户更方便地管理项目依赖项。 安装…...
使用proxman对iOS真机进行抓包
1 打开手机的safari 输入地址 http://proxy.man/ssl 2 下载证书代开设置页面,安装证书 设置信任证书 打开手机设置 ,点击通用 点击关于本机、 点击证书信任设置 打开信任设置开关 4 设置手机代理 查看需要设置的代理地址 打开界面 在手机中按…...
sdk manager (ubuntu20.4) 安装
1、首先下载sdk manager 1.9.3 下载链接 https://www.baidu.com/link?urlVXJhUqxxhS3eFK3bOPTzi5LFl6ybeW3JwDY1CwANaPf1gvO3IxQKzY547NIe53x1blJxnAXg7FTRTvs-cnfnVa&wd&eqida22baa7b0004ca980000000664e2d426 当然要登录自己的账号才能成功下载,下载对应…...
Oracle修改字符集为SIMPLIFIED CHINESE_CHINA.ZHS16GBK
查询字符集 select userenv(language) from dual;修改前字符集为:SIMPLIFIED CHINESE_CHINA.AL32UTF8 SQL> shutdown immediate; Database closed. Database dismounted. ORACLE instance shut down. SQL> startup mount; ORACLE instance started. Total …...
函数的参数传递和返回值-PHP8知识详解
本文学习的是《php8知识详解》中的《函数的参数传递和返回值》。主要包括:向函数传递参数值、向函数传递参数引用、函数的返回值。 1、向函数传递参数值 函数是一段封闭的程序,有时候,程序员需要向函数传递一些数据进行操作。可以接受传入参…...
【Redis】 Redis短连接的性能优化
Redis短连接的性能优化 1. 问题 通过历史监控我们可以发现用户在频繁使用短连接的时候Redis的cpu使用率有显著的上升 2. 排查 通过扁鹊查看但是Redis的cpu运行情况如下 从扁鹊我们可以看到Redis在freeClient的时候会频繁调用listSearchKey,并且该函数占用了百分…...
无涯教程-分类算法 - 逻辑回归
逻辑回归是一种监督学习分类算法,用于预测目标变量的概率,目标或因变量的性质是二分法,这意味着将只有两种可能的类。 简而言之,因变量本质上是二进制的,其数据编码为1(代表成功/是)或0(代表失败/否)。 在数学上&…...
URL中传递JSON字符串
今天遇见了一个需求,从post请求中在url里传递json字符串, 就是路径?参数11那种情况 最后怎么解决的呢? 需要使用前端方法,先用JSON.stringify格式化成字符串,再用encodeURIComponent把JSON里面的符号转转为url支持的…...
Python Opencv实践 - Sobel边缘检测
import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/pomeranian.png", cv.IMREAD_GRAYSCALE) print(img.shape)#Sobel边缘检测 #cv.sobel( src, ddepth, dx, dy[,ksize[, scale[, delta[, borderType]]]] ) #src:…...
IDEA快速设置Services窗口
现在微服务下面会有很多SpringBoot服务,Services窗口方便我们管理各个SpringBoot服务,但有时IDEA打开项目后无法的看到Services窗口,以下步骤可以解决!...
【CSS】CSS 背景设置 ( 背景半透明设置 )
一、背景半透明设置 1、语法说明 背景半透明设置 可以 使用 rgba 颜色值设置半透明背景 ; 下面的 CSS 样式中 , 就是 设置黑色背景 , 透明度为 20% ; background: rgba(0, 0, 0, 0.2);颜色的透明度 alpha 取值范围是 0 ~ 1 之间 , 在使用时 , 可以 省略 0.x 前面的 0 , 直接…...
基于android的学生公寓后勤系统/学生公寓管理系统APP
摘 要 随着网络科技的发展,移动智能终端逐渐走进人们的视线,相关应用越来越广泛,并在人们的日常生活中扮演着越来越重要的角色。因此,关键应用程序的开发成为影响移动智能终端普及的重要因素,设计并开发实用、方便的应…...
跳跃游戏 II
跳跃游戏 II 题目: 给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i j] 处:0 < j < nums[i] i j < n 返回到达…...
51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
【Veristand】Veristand环境安装教程-Linux RT / Windows
首先声明,此教程是针对Simulink编译模型并导入Veristand中编写的,同时需要注意的是老用户编译可能用的是Veristand Model Framework,那个是历史版本,且NI不会再维护,新版本编译支持为VeriStand Model Generation Suppo…...
DiscuzX3.5发帖json api
参考文章:PHP实现独立Discuz站外发帖(直连操作数据库)_discuz 发帖api-CSDN博客 简单改造了一下,适配我自己的需求 有一个站点存在多个采集站,我想通过主站拿标题,采集站拿内容 使用到的sql如下 CREATE TABLE pre_forum_post_…...
