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查询。

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

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

相关文章

zabbix 7.0 安装(服务器、前端、代理等)

https://www.zabbix.com/download 使用上面的地址&#xff0c;按教程执行命令安装

andrular输入框input监听值传递

效果图&#xff1a; step1: E:\projectgood\ajnine\untitled4\src\app\apple\apple.component.html <button mat-button (click)“openDialog()”>Open dialog step2: E:\projectgood\ajnine\untitled4\src\app\apple\apple.component.ts import {Component, inject}…

考公人数攀升?地信、测绘、地质、遥感等专业,能报考哪些单位

近年来&#xff0c;考公人数持续飙升&#xff0c;国考报名人数更逐年攀升。2025年国家公务员考试共有341.6万人通过资格审查&#xff0c;报录比达86:1。国考报名人数再创新高。 国家公务员考试时间安排 地理学相关岗位分析 地信属于地理科学类&#xff0c;测绘类中不包括地信&…

Pr 视频效果:超级键

视频效果/键控/超级键 Keying/Ultra Key 超级键 Ultra Key效果是 Premiere Pro 中功能强大的抠像工具&#xff0c;主要用于绿幕/蓝幕抠像。通过选择要抠除的颜色&#xff08;通常是绿幕或蓝幕的颜色&#xff09;&#xff0c;即可以将该颜色的像素设为透明&#xff0c;实现主体与…

24-11-1-读书笔记(三十一)-《契诃夫文集》(五)下([俄] 契诃夫 [译] 汝龙)生活乏味但不乏魅力。

文章目录 《契诃夫文集》&#xff08;五&#xff09;下&#xff08;[俄] 契诃夫 [译] 汝龙&#xff09;生活乏味但不乏魅力。目录阅读笔记总结 《契诃夫文集》&#xff08;五&#xff09;下&#xff08;[俄] 契诃夫 [译] 汝龙&#xff09;生活乏味但不乏魅力。 休息&#xff0c…

戴尔电脑 Bios 如何进入?Dell Bios 进入 Bios 快捷键是什么?

BIOS&#xff08;基本输入输出系统&#xff09;是计算机启动时运行的第一个程序&#xff0c;它负责初始化硬件并加载操作系统。对于戴尔电脑用户来说&#xff0c;有时可能需要进入 BIOS 进行一些特定的设置调整&#xff0c;比如更改启动顺序、调整性能选项或解决硬件兼容性问题…

【C++】内存管理(二):operator new/delete

大家好&#xff0c;我是苏貝&#xff0c;本篇博客带大家了解C的operator new/delete&#xff0c;如果你觉得我写的还不错的话&#xff0c;可以给我一个赞&#x1f44d;吗&#xff0c;感谢❤️ 目录 1 new/delete的底层2 new/delete的底层调用顺序3 delete[ ]调用析构函数的次数…

acmessl.cn提供接口API方式申请免费ssl证书

目录 一、前沿 二、API接口文档 1、证书可申请列表 简要描述 请求URL 请求方式 返回参数说明 备注 2、证书申请 简要描述 请求URL 请求方式 业务参数 返回示例 返回参数说明 备注 3、证书查询 简要描述 请求URL 请求方式 业务参数 返回参数说明 备注 4、证…

【docker】docker 环境配置及安装

本文介绍基于 官方存储库 docker 的环境配置、安装、代理配置、卸载等相关内容。 官方安装文档说明&#xff1a;https://docs.docker.com/engine/install/ubuntu/ 虚拟机环境 Ubuntu 20.04.6 LTS 安装步骤 添加相关依赖 sudo apt-get update sudo apt-get install ca-certifi…

机器学习在时间序列预测中的应用与实现——以电力负荷预测为例(附代码)

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 1. 引言 随着数据采集技术的发展&#xff0c;时间序列数据在各个领域中的应用越来越广泛。时间序列预测旨在基于过去的时间数据来…

uniapp+vue加油服务系统 微信小程序

文章目录 项目介绍具体实现截图技术介绍mvc设计模式小程序框架以及目录结构介绍错误处理和异常处理java类核心代码部分展示详细视频演示源码获取 项目介绍 基于微信小程序的加油服务系统设计为微信小程序和后台管理两个服务端&#xff0c;并对此设计相应的功能模块如下&#x…

大数据新视界 -- 大数据大厂之 Impala 资源管理:并发控制的策略与技巧(下)(6/30)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

Linux(CentOS)设置防火墙开放8080端口,运行jar包,接收请求

1、查看防火墙状态 systemctl status firewalld 防火墙开启状态 2、运行 jar 包&#xff0c;使用8080端口 程序正常启动 3、使用 postman 发送请求&#xff0c;失败 4、检查端口是否开放&#xff08;需更换到 root 用户&#xff09; firewall-cmd --zonepublic --query-por…

跳表原理-课堂笔记

课程地址 跳表是一种基于随机化的有序数据结构&#xff0c;它提出是为了赋予有序单链表以 O(logn) 的快速查找和插入的能力 创建 首先在头部创建一个 sentinel 节点&#xff0c;然后在 L1 层采用“抛硬币”的方式来决定 L0 层的指针是否增长到 L1 层 例如上图中&#xff0c;L…

Mybatis学习笔记(二)

八、多表联合查询 (一) 多表联合查询概述 在开发过程中单表查询不能满足项目需求分析功能&#xff0c;对于复杂业务来讲&#xff0c;关联的表有几张&#xff0c;甚至几十张并且表与表之间的关系相当复杂。为了能够实业复杂功能业务&#xff0c;就必须进行多表查询&#xff0c…

基于 JAVASSM(Java + Spring + Spring MVC + MyBatis)框架开发一个九宫格日志系统

基于 JAVASSM&#xff08;Java Spring Spring MVC MyBatis&#xff09;框架开发一个九宫格日志系统 步骤一&#xff1a;需求分析 明确系统需要实现的功能&#xff0c;比如&#xff1a; 用户注册和登录添加日志&#xff08;包含标题、内容、图片&#xff09;查看日志列表…

rom定制系列------小米8青春版定制安卓14批量线刷固件 原生系统

&#x1f49d;&#x1f49d;&#x1f49d;小米8青春版。机型代码platina。官方最终版为 12.5.1安卓10的版本。客户需要安卓14的固件以便使用他们的软件。根据测试&#xff0c;原生pixeExpe固件适配兼容性较好。为方便客户批量进行刷写。修改固件为可fast批量刷写。整合底层分区…

浅谈UI自动化

⭐️前言⭐️ 本篇文章围绕UI自动化来展开&#xff0c;主要内容包括什么是UI自动化&#xff0c;常用的UI自动化框架&#xff0c;UI自动化原理等。 &#x1f349;欢迎点赞 &#x1f44d; 收藏 ⭐留言评论 &#x1f349;博主将持续更新学习记录收获&#xff0c;友友们有任何问题…

blender导入的图片渲染看不见,图片预览正常,但渲染不出

在使用Blender时&#xff0c;我们经常会遇到导入图片后在预览渲染中显示&#xff0c;但在实际渲染时图片消失的问题。本文将提供详细的解决方法&#xff0c;帮助大家解决“Blender导入的图片渲染图像不显示”的问题。 问题原因 导入的图片在Blender中只是一张图&#xff0c;并…

vue--vueCLI

何为CLI ■ CLI是Command-Line Interface,俗称脚手架. ■ 使用Vue.js开发大型应用时&#xff0c;我们需要考虑代码目录结构、项目结构和部署、热加载、代码单元测试等事情。&#xff08;vue 脚手架的作用&#xff09;&#xff0c; 而通过vue-cli即可&#xff1a;vue-cli 可以…