Redis数据库测试和缓存穿透、雪崩、击穿
Redis数据库测试实验
实验要求
1.新建一张user表,在表内插入10000条数据。
2.①通过jdbc查询这10000条数据,记录查询时间。
②通过redis查询这10000条数据,记录查询时间。
3.①再次查询这一万条数据,要求根据年龄进行排序,mysql和redis各实现一次。
4.上面排序后的前5人可进行抽奖,每人有一次抽奖机会,抽奖奖品随意设计,抽奖方式通过redis实现。
1.基本准备
先下载好jar包

在根目录下,新建lib文件夹,并将两个jar包移动到lib文件夹中
在IDEA中,右键点击lib,选择“添加为库”

两个jar包显示可展开即为成功。
2.mysql建立用户表user
CREATE TABLE `user` (`id` int primary key AUTO_INCREMENT,`name` varchar(10) COMMENT '姓名',`age` int COMMENT '年龄'
) ;
3.为mysql和redis添加数据
(1)获取数据库连接,并为mysql添加数据
//获取数据库连接public Connection getConnection() {System.out.println("获取数据库连接");String url = "jdbc:mysql://localhost:3306/homework";String username = "root";String password = "123456";Connection conn = null;try {conn = DriverManager.getConnection(url, username, password);} catch (SQLException e) {e.printStackTrace();}return conn;}
//mysql添加数据public void addMysql() {System.out.println("mysql添加数据");Connection conn = null;PreparedStatement ps = null;conn = getConnection();try {Random random = new Random();for (int i = 0; i < 10000; i++) {String name = "Name" + i;int age = random.nextInt(100) + 1;ps = conn.prepareStatement("INSERT INTO user (name,age) VALUES (?,?)");ps.setString(1, name);ps.setInt(2, age);ps.executeUpdate();}} catch (SQLException e) {e.printStackTrace();} finally {try {ps.close();conn.close();} catch (SQLException e) {throw new RuntimeException(e);}}}
(2)将Mysql数据转储到redis中
// 将Mysql数据库数据转储到Redispublic void addRedis() {System.out.println("redis添加数据");Connection conn = null;PreparedStatement ps = null;ResultSet rs = null;conn = getConnection();try {ps = conn.prepareStatement("select * from user");rs = ps.executeQuery();Jedis jedis = new Jedis("localhost", 6379);while (rs.next()) {String id = String.valueOf(rs.getInt("id"));String name = rs.getString("name");int age = rs.getInt("age");// 使用有序集合存储学生ID和年龄,以便进行排序jedis.zadd("UserByAge", age, id);// 存储学生数据jedis.hset("user:" + id, "name", name);jedis.hset("user:" + id, "age", String.valueOf(age));}jedis.close();} catch (SQLException e) {e.printStackTrace();} finally {try {rs.close();ps.close();conn.close();} catch (SQLException e) {throw new RuntimeException(e);}}}
4.实现mysql和redis查询,并比较查询时间
(1)mysql查询
//mysql查询public void queryDataWithJDBC() {Connection conn = null;PreparedStatement ps = null;ResultSet rs = null;conn = getConnection();try {ps = conn.prepareStatement("select * from user");rs = ps.executeQuery();while (rs.next()) {
// System.out.println("ID: " + rs.getInt("id") + ", Name: " + rs.getString("name") + ", Age: " + rs.getInt("age"));}} catch (SQLException e) {e.printStackTrace();} finally {try {rs.close();ps.close();conn.close();} catch (SQLException e) {throw new RuntimeException(e);}}}
(2)redis查询
//redis查询public void queryDataWithRedis() {Jedis jedis = new Jedis("localhost", 6379);Set<String> keys = jedis.keys("user:*");for (String key : keys) {Map<String, String> user = jedis.hgetAll(key);
// System.out.println("Key: " + key + ", Value: " + user);}jedis.close();}
(3)记录并比较查询时间
// 比较查询时间public void compareTime() {// 通过jdbc查询这10000条数据,记录查询时间long start = System.currentTimeMillis();queryDataWithJDBC();long end = System.currentTimeMillis();System.out.println("JDBC查询时间: " + (end - start) + "ms");// 通过redis查询这10000条数据,记录查询时间start = System.currentTimeMillis();queryDataWithRedis();end = System.currentTimeMillis();System.out.println("Redis查询时间: " + (end - start) + "ms");}
5.根据年龄进行排序
(1)mysql排序
//mysql实现排序public void queryAndSortDataWithJDBC() {Connection conn = null;PreparedStatement ps = null;ResultSet rs = null;conn = getConnection();try {ps = conn.prepareStatement("SELECT * FROM user ORDER BY age");rs = ps.executeQuery();System.out.println("mysql实现排序:");while (rs.next()) {System.out.println("ID: " + rs.getInt("id") + ", Name: " + rs.getString("name") + ", Age: " + rs.getInt("age"));}} catch (SQLException e) {e.printStackTrace();} finally {try {rs.close();ps.close();conn.close();} catch (SQLException e) {throw new RuntimeException(e);}}}
(2)redis排序
//redis实现排序public void queryAndSortDataWithRedis() {Jedis jedis = new Jedis("localhost", 6379);List<Tuple> users = jedis.zrangeWithScores("UserByAge", 0, -1);System.out.println("redis实现排序:");for (Tuple user : users) {String id = user.getElement();double age = user.getScore();String name = jedis.hget("user:" + id, "name");System.out.println("ID: " + id + ", Name: " + name + ", Age: " + (int) age);}jedis.close();}
6.抽奖功能
//抽奖public void lottery() {Jedis jedis = new Jedis("localhost", 6379);// 添加奖品String[] prizes = {"锅", "碗", "瓢", "盆", "金元宝"};for (String prize : prizes) {jedis.sadd("prizes", prize);}// 年龄最小的前5人System.out.println("年龄最小的前5人:");List<Tuple> youngestUsers = jedis.zrangeWithScores("UserByAge", 0, 4);for (Tuple user : youngestUsers) {String id = user.getElement();double age = user.getScore();String name = jedis.hget("user:" + id, "name");String prize = jedis.srandmember("prizes");System.out.println("恭喜 " + name + " 获得了抽奖机会!奖品是:" + prize);}jedis.close();}
7.主函数
public static void main(String[] args) throws SQLException {JedisHomework jedisHomework = new JedisHomework();jedisHomework.addMysql();jedisHomework.addRedis();jedisHomework.compareTime();jedisHomework.queryAndSortDataWithJDBC();jedisHomework.queryAndSortDataWithRedis();jedisHomework.lottery();}
Redis中的缓存穿透、雪崩、击穿的原因以及解决方案
1.缓存击穿
(1)产生原因
在高并发访问下,某个热点key在缓存中过期后,大量并发请求同时查询数据库,导致数据库压力激增的现象。
(2)解决方案
合理的过期时间:将热点数据设置为永远不过期
使用互斥锁:基于redis or zookeeper实现互斥锁,等待第一个请求构建完缓存之后,再释放锁,进而其他请求才能通过该key访问数据。
2.缓存雪崩
(1)产生原因
由于缓存服务器在同一时间大面积失效或宕机,导致大量请求直接打到数据库,瞬间引发数据库压力激增,甚至导致数据库崩溃。
(2)解决方案
事前:redis 高可用,主从+哨兵,redus cluster,避免全盘崩溃
事中:本地缓存 + hystrix 限流&降级,避免 MySQL被打死。同时设置合理的过期时间。
事后:redis持久化,一旦重启,自动从磁盘上加载数据,快速回复缓存数据。
3.缓存穿透
(1)产生原因
查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,进而给数据库带来压力。
缓存穿透很有可能是黑客攻击所为,黑客通过发送大量的高并发的无法响应的请求给服务器,由于请求的资源根本就不存在,DB(数据库)就很容易被打垮了。
(2)解决方案
缓存空对象:对查询结果为空的情况,也将其缓存起来,并设置合理的过期时间。
参数校验:在接收到请求之前进行参数校验,判断请求参数是否合法。
布隆过滤器:判断请求的参数是否存在于缓存或数据库中。
4.三者的异同
相同点:大量的请求在redis上得不到响应,那么就会导致这些请求会直接去访问DB,导致DB的压力瞬间变大而卡死或者宕机。
不同点:缓存击穿是某个热点过期后,导致大量请求访问DB;
缓存雪崩是多个key过期后,导致大量请求访问DB;
缓存穿透是不存在的key收到大量请求,每次请求都要到DB查询。
相关文章:
Redis数据库测试和缓存穿透、雪崩、击穿
Redis数据库测试实验 实验要求 1.新建一张user表,在表内插入10000条数据。 2.①通过jdbc查询这10000条数据,记录查询时间。 ②通过redis查询这10000条数据,记录查询时间。 3.①再次查询这一万条数据,要求根据年龄进行排序&#…...
[vulnhub] DarkHole: 2
https://www.vulnhub.com/entry/darkhole-2,740/ 端口扫描主机发现 探测存活主机,185是靶机 # nmap -sP 192.168.75.0/24 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-11-08 18:02 CST Nmap scan report for 192.168.75.1 Host is up (0.…...
《XGBoost算法的原理推导》12-2 t轮迭代中对样本i的预测值 公式解析
本文是将文章《XGBoost算法的原理推导》中的公式单独拿出来做一个详细的解析,便于初学者更好的理解。 好的,公式(12-2)表示的是 XGBoost 在第 t t t 轮迭代中对样本 i i i 的预测值。它说明了在第 t t t 轮迭代中,模型的预测是通过累加之前…...
./bin/mindieservice_daemon启动成功
接MindIE大模型测试及报错Fatal Python error: PyThreadState_Get: the function must be called with the GIL held,-CSDN博客经过调整如下红色部分参数,昇腾310P3跑起来了7b模型: rootdev-8242526b-01f2-4a54-b89d-f6d9c57c692d-qjhpf:/home/apulis-de…...
Linux: network: ip link M-DOWN的具体含义是什么?
文章目录 参考简介实例代码解释openstack上的显示如果是在一个interface上建立了vlan参考 https://unix.stackexchange.com/questions/348327/using-ip-what-does-m-down-mean www.policyrouting.org/iproute2.doc.html#ss9.1 简介 是指上一级的接口的状态。 实例 4: ersp…...
Spring中的过滤器和拦截器
Spring中的过滤器和拦截器 一、引言 在Spring框架中,过滤器(Filter)和拦截器(Interceptor)是实现请求处理的两种重要机制。它们都基于AOP(面向切面编程)思想,用于在请求的生命周期…...
leetcode20.括号匹配
题目描述 给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。 有效字符串需满足: 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 每个…...
Unity性能优化-具体操作
批量渲染是通过减少CPU向GPU发送渲染命令(DrawCall)的次数,以及减少GPU切换渲染状态的次数,尽量让GPU一次多做一些事情,来提升逻辑线和渲染线的整体效率。 Draw Call性能消耗原因是命令从Runtime到Driver的过程中&…...
【嵌入式开发——ARM】1ARM架构
嵌入式领域,使用ARM架构的芯片公司可不占少数吧,intel的x86架构主要占据PC、服务器市场,ARM架构主要占据移动市场。x86架构和ARM架构不同的主要原因,是背后使用的计算机指令集不同。计算机有自己的语言系统(汇编&#…...
Linux中.NET读取excel组件,不会出现The type initializer for ‘Gdip‘ threw an exception异常
组件,可通过nuget安装,直接搜名字: ExcelDataReader using ConsoleAppReadFileData.Model; using ExcelDataReader; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Task…...
mmclassification的配置文件样本
# 需要修改的参数 img_size 480 class_name [fuqi,ok] num_classes len(class_name) data_root /home/apulis-test/teamdata/yz_dataset/fuqi max_epochs300 val_interval1 train_batch_size 16 val_batch_size 1 load_from "swin_tiny_224_b16x64_300e_imagenet_…...
Java基础——类和对象的定义链表的创建,输出
目录 什么是类? 什么是对象? 如何创建链表? 尾插法: 头插法: 输出链表的长度 输出链表的值 什么是类? 创建Java程序必须创建一个类class. .java程序需要经过javac指令将文件翻译为.class字节码文件,…...
Linux应用项目之量产工具(一)——显示系统
目录 前言 项目特点及介绍 ① 简单易用 ② 软件可配置、易扩展 ③ 纯 C 语言编程 软件总框架 显示系统 1.数据结构抽象 disp_manager.h 2.Framebuffer编程 framebuffer.c 3.显示管理 disp_manager.c 4.单元测试 disp_test.c 顶层目录Makefile 顶层目录Makefil…...
Python小白学习教程从入门到入坑------第二十九课 访问模式(语法进阶)
目录 一、访问模式 1.1 r 1.2 w 1.3 1.3.1 r 1.3.2 w 1.3.3 a 1.4 a 一、访问模式 模式可做操作若文件不存在是否覆盖r只能读报错-r可读可写报错是w只能写创建是w可读可写创建是a只能写创建否,追加写a可读可写创建否,追加写 1.1 r r&…...
使用 PageHelper 在 Spring Boot 项目中实现分页查询
目录 前言1. 项目环境配置1.1 添加 PageHelper 依赖1.2 数据库和 MyBatis 配置 2. 统一的分页响应类3. 使用 PageHelper 实现分页查询3.1 Service 层分页查询实现3.2 PageHelper 分页注意事项 4. 控制层调用示例5. 常见问题与解决方案5.1 java.util.ArrayList cannot be cast t…...
深度学习-张量相关
一. 张量的创建 张量简介 张量是pytorch的基本数据结构 张量,英文为Tensor,是机器学习的基本构建模块,是以数字方式表示数据的形式。 例如,图像可以表示为形状为 [3, 224, 224] 的张量,这意味着 [colour_channels, h…...
电脑提示xinput1_3.dll丢失怎么解决,分享6种有效的解决方法
xinput1_3.dll 是一个动态链接库(DLL)文件,它在Windows操作系统中扮演着重要的角色,特别是在处理游戏控制器和其他输入设备的交互方面。这个文件是Microsoft DirectX软件包的一部分,DirectX是微软公司开发的一个多媒体…...
【计网】数据链路层笔记
【计网】数据链路层 数据链路层概述 数据链路层在网络体系结构中所处的地位 链路、数据链路和帧 链路(Link)是指从一个节点到相邻节点的一段物理线路(有线或无线),而中间没有任何其他的交换节点。 数据链路(Data Link)是基于链路的。当在一条链路上传送数据时&a…...
蓝牙FTP 协议详解及 Android 实现
文章目录 前言一、什么是蓝牙 FTP 协议?二、FTP 的工作流程1.蓝牙设备初始化2. 设备发现与配对3. 建立OBEX FTP 连接4. 文件传输文件上传(通过OBEX PUT命令)文件下载(通过OBEX GET命令) 5. 关闭OBEX会话 三、进阶应用与…...
【前端】Svelte:动画效果
在现代前端开发中,动画效果可以大大提升用户体验,使应用更生动、易用。Svelte 提供了灵活的动画 API,让开发者能够快速实现从简单过渡到复杂动画的各种效果。本文将系统性地介绍 Svelte 的动画功能,并通过多个示例演示如何创建动感…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...
HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...
Vue 模板语句的数据来源
🧩 Vue 模板语句的数据来源:全方位解析 Vue 模板(<template> 部分)中的表达式、指令绑定(如 v-bind, v-on)和插值({{ }})都在一个特定的作用域内求值。这个作用域由当前 组件…...
如何配置一个sql server使得其它用户可以通过excel odbc获取数据
要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据,你需要完成以下配置步骤: ✅ 一、在 SQL Server 端配置(服务器设置) 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到:SQL Server 网络配…...
