Redis——缓存设计与优化

讲解Redis的缓存设计与优化,以及在生产环境中遇到的Redis常见问题,例如缓存雪崩和缓存穿透,还讲解了相关问题的解决方案。

1、Redis缓存的优点和缺点

1.1、缓存优点:

  • 高速读写:Redis可以帮助解决由于数据库压力造成的延迟现象,针对很少改变的数据并且经常使用的数据,我们可以把这些数据放入内存中。这样一方面可以减小数据库压力,另一方面可以提高读写效率。
  • 降低后端负载:后端服务器通过缓存降低负载,业务端使用Redis可以降低后端数据库MySQL的负载等。

1.2、缓存缺点:

  • 数据不一致:程序的缓存层和数据层有时会不一致,这和更新数据策略有关。
  • 代码维护成本:原本只需要读写MySQL就能实现功能,但加入了Redis缓存之后就要去维护缓存中的数据,增加了代码复杂度。
  • 堆内缓存可能带来内存溢出的风险,从而影响用户进程:在Java虚拟机的EhCache、LoadingCache、Java虚拟机栈、方法区、本地方法栈、程序计数器中,堆内缓存可能会带来内存溢出的风险,从而影响用户进程。

2、缓存雪崩

2.1、什么是缓存雪崩

缓存雪崩是指数据未加载到缓存中,或者缓存在同一时间大面积失效,导致所有请求都查询数据库,从而导致数据库CPU和内存负载过高,甚至数据库宕机。

2.2、有什么解决方案来防止缓存雪崩

(1)使用互斥锁(mutex)。使用互斥锁来防止缓存雪崩,使用Redis的SETNX命令去设置一个mutex key,当操作返回成功时,再执行查询数据库操作并回设Redis缓存。否则,就重试执行缓存的GET方法。

(2)缓存预热。缓存预热就是应用上线后,将相关的缓存数据直接加载到缓存系统中。这样用户就可以直接查询事先被预热的缓存数据。

(3)双层缓存策略。Cache 1为原始缓存,Cache 2为复制缓存。Cache 1失效时,可以访问Cache 2。Cache 1缓存失效时间设置为短期,Cache 2缓存失效时间设置为长期。

(4)定时更新缓存策略。对失效性要求不高的缓存,在容器启动初始化加载时采用定时任务更新或移除缓存。

(5)设置不同的过期时间,让缓存失效的时间点尽量均匀。

3、缓存穿透

3.1、什么是缓存穿透

缓存就是数据交换的缓冲区。缓存的主要作用是提高查询效率。在企业开发的软件系统中常常使用Redis作为缓存中间件,当请求到达服务器端时,优先查询缓存中的数据,当缓存中不存在时,再查询数据库,如果在数据库中查询到数据会将数据写回缓存,使得下一次同样的请求能够在缓存中直接查询到数据。一些攻击性请求会特意查询缓存中不存在的数据,产生缓存穿透。

缓存穿透是指查询一个不存在的数据。例如,Redis在缓存中没有查询到要查询的数据,需要去数据库查询,如果查询不到数据则不写入缓存,这将导致这个不存在的数据在每次请求时都到数据库查询,进而对数据库产生流量冲击造成缓存穿透。

3.2、有什么解决方案来防止缓存穿透

(1)采用布隆过滤器。

(2)缓存空值。如果一个查询返回的数据为空值,那么不管是数据不存在,还是系统故障,程序仍然会把这个空值进行缓存处理,但它的过期时间会很短,可能不超过5min。通过设置的默认值将该数据直接存放到缓存中,这样第二次在缓存中就可以查询到值了,而不会继续访问数据库。

4、布隆过滤器

4.1、布隆过滤器简介

布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率高和查询时间短,缺点是有一定的误识别率和元素删除困难。

布隆过滤器是一种空间效率很高的随机数据结构,它利用位数组很简洁地表示一个集合,并能判断一个元素是否属于这个集合。布隆过滤器由一个很长的位数组和一系列散列函数组成,数组的每个元素都只占1 bit空间,并且每个元素只能为0或1。

布隆过滤器还拥有k个散列函数,当一个元素加入布隆过滤器时,会使用k个散列函数对其进行k次计算,得到k个散列值,并且根据得到的k个散列值,在位数组中把对应位置的值置为1。判断某个元素是否在布隆过滤器中,就对该元素进行k次散列计算,判断得到的值在位数组中对应位置的值是否都为1,如果每个元素都为1,就说明这个元素在布隆过滤器中。

将数据库中需要查询的数据放入系统缓存中的布隆过滤器中,当请求向后台系统查询数据时,先去系统缓存中的布隆过滤器中进行查找,如果查询的数据在布隆过滤器中不存在,就不用查询数据库了,直接给请求返回一个未查询到数据的结果,从而避免了对数据库的频繁查询。

布隆过滤器是一个判断元素是否属于集合的快速的概率算法。布隆过滤器有可能会出现错误判断,但不会漏掉判断。也就是说,如果布隆过滤器判断元素不在集合中,那么肯定不在;如果判断元素在集合中,那么会有一定的概率判断错误。因此,布隆过滤器不适合那些零错误的应用场景。而在能容忍低错误率的应用场景中,布隆过滤器比其他常见的算法(如散列函数、折半查找)极大节省了空间,如下图所示:
在这里插入图片描述
布隆过滤器很常用的一个功能是去重,比如在爬虫中有一个常见的需求:目标网站的URL可以有成千上万个,怎么判断某个URL是否被爬虫爬取过呢?一个简单的方法是,可以把爬虫爬取过的每个URL存入数据库中,每次一个新的URL过来就到数据库查询是否爬取过。例如,SELECT*FROM spider WHERE url=‘http://www.163.com’。

但是随着爬虫爬取过的URL越来越多,每次请求查询时都要访问数据库一次,判断某个URL是否访问过使用SQL查询效率并不高。除了数据库之外,还可以使用Redis的Set数据类型满足这个需求,并且其性能优于数据库。但是Redis也存在一个问题,它会耗费过多的内存,这时候就可以使用布隆过滤器来解决去重问题。相比于数据库和Redis,使用布隆过滤器可以很好地避免性能和内存占用的问题。

我们通常使用Redis作为数据缓存,当收到请求时先通过key去Redis缓存中查询,如果查询的数据在Redis缓存中不存在,就会去查询数据库中的数据。如果这种请求量很大,会给数据库造成很大的查询压力,从而影响系统的性能,这时就需要用到布隆过滤器来解决缓存穿透问题了。

解决缓存穿透的方法:

方法一:当数据库和Redis中都不存在key,查询数据库会返回null。需要在Redis中使用SETEX key null expireTime设置一个过期时间expireTime,这样当再次请求key时Redis将直接返回null,而不用再次查询数据库。

方法二:使用Redis提供的布隆过滤器模块RedisBloom,同样是将存在的key放入布隆过滤器中。当收到请求时先在布隆过滤器中查询key是否存在,如果key不存在直接返回null,不必再次查询数据库。

布隆过滤器的用途是判断过滤器中是否存在该数据,从而减少没有必要的数据库请求。

4.2、Redis加载布隆过滤器模块

Redis官方提供的布隆过滤器在Redis 4.0发布以后才正式推出。布隆过滤器可作为一个插件加载到Redis服务器中,给Redis提供强大的布隆去重功能。在本小节中,我们将学习如何在Redis服务器上加载布隆过滤器模块。

在GitHub搜索RedisBloom下载最新发布的源代码,单击页面的“Clone or download”按钮后选择“Download ZIP”,下载RedisBloom-master.zip到本地硬盘,如下图所示:
在这里插入图片描述
上传RedisBloom-master.zip到Linux服务器,在Linux服务器上进行解压缩和编译:

$ unzip RedisBloom-master.zip 
$ cd RedisBloom-master/ 
$ make

4.3、在项目中使用布隆过滤器

pom.xml文件中引入以下类库:

<dependencies> <dependency> <groupId>com.redislabs</groupId> <artifactId>jrebloom</artifactId> <version>1.0.1</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.1.0</version> </dependency> </dependencies>

新建测试类RedisbloomDemo。本实例使用“RedisbloomDemo.java”,内容如下:

 
import io.rebloom.client.Client; public class RedisbloomDemo { public static void main(String[] args) { // 创建客户端,Jedis实例 Client client = new Client("192.168.11.15", 6379); String urlsBloomKey = "urls"; // 创建一个有初始值和出错率的布隆过滤器 client.createFilter(urlsBloomKey,1000,0.01); // 在布隆过滤器新增一个key-value键值对 boolean url1 = client.add(urlsBloomKey,"http://www.163.com"); System.out.println("url1 add :" + url1); boolean url2 = client.add(urlsBloomKey,"http://www.cnblogs.com"); System.out.println("url2 add :" + url1); // 某个value是否在布隆过滤器中存在 boolean exists = client.exists(urlsBloomKey, "http://www.163.com"); System.out.println("http://www.163.com 是否存在: " + exists); } 
}

该程序输出如下:

url1 add :true 
url2 add :true 
http://www.163.com 是否存在: true

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

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

相关文章

安全的接口访问策略

渗透测试 一、Token与签名 一般客户端和服务端的设计过程中&#xff0c;大部分分为有状态和无状态接口。 一般用户登录状态下&#xff0c;判断用户是否有权限或者能否请求接口&#xff0c;都是根据用户登录成功后&#xff0c;服务端授予的token进行控制的。 但并不是说有了tok…

【LeetCode】332. 重新安排行程(困难)——代码随想录算法训练营Day30

题目链接&#xff1a;332. 重新安排行程 题目描述 给你一份航线列表 tickets &#xff0c;其中 tickets[i] [fromi, toi] 表示飞机出发和降落的机场地点。请你对该行程进行重新规划排序。 所有这些机票都属于一个从 JFK&#xff08;肯尼迪国际机场&#xff09;出发的先生&a…

JVM-运行时数据区程序计数器

运行时数据区 Java虚拟机在运行Java程序过程中管理的内存区域&#xff0c;称之为运行时数据区。《Java虚拟机规范》中规定了每一部分的作用。 程序计数器的定义 程序计数器&#xff08;Program Counter Register&#xff09;也叫PC寄存器&#xff0c;每个线程会通过程序计数器…

1.3 Verilog 环境搭建详解教程

学习 Verilog 做仿真时&#xff0c;可选择不同仿真环境。FPGA 开发环境有 Xilinx 公司的 ISE&#xff08;目前已停止更新&#xff09;&#xff0c;VIVADO&#xff1b;因特尔公司的 Quartus II&#xff1b;ASIC 开发环境有 Synopsys 公司的 VCS &#xff1b;很多人也在用 Icarus…

PyTorch 2.2 中文官方教程(三)

使用 PyTorch 构建模型 原文&#xff1a;pytorch.org/tutorials/beginner/introyt/modelsyt_tutorial.html 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 注意 点击这里下载完整示例代码 介绍 || 张量 || 自动微分 || 构建模型 || TensorBoard 支持 || 训练模型 ||…

Java风暴:打造高效作家信息管理平台

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

Web项目利用EasyExcel实现Excel的导出操作

早期Java使用的一些解析&#xff0c;到处excel的框架存在种种问题被遗弃&#xff0c;现在使用阿里巴巴所提供的EasyExcel已成为一种主流&#xff0c;本篇将详细介绍该功能在Web项目中如何实际应用。 详细操作文档&#xff1a;写Excel | Easy Excel 一、项目演示 在后台管理界…

Nginx与history路由模式:刷新页面404问题

使用nginx部署前端项目&#xff0c;路由模式采用history模式时&#xff0c;刷新页面之后&#xff0c;显示404。 路由模式 前端路由的基本作用为&#xff1a; ①当浏览器地址变化时&#xff0c;切换页面&#xff1b; ②点击浏览器后退、前进按钮时&#xff0c;更新网页内容&…

基于ISO13400 (DoIP) 实现车辆刷写

近年来&#xff0c;在整车研发中基于以太网实现车辆高带宽通讯无疑是人们热议的话题。无论是车内基于车载以太网来减少线束成本&#xff0c;实现ADAS、信息娱乐系统等技术&#xff0c;还是基于新的电子电气架构以及远程诊断需求来实现以太网诊断&#xff08;DoIP&#xff09;&a…

BUGKU-WEB 留言板

题目描述 题目无需登录后台&#xff01;需要xss平台接收flag&#xff0c; http协议需要http协议的xss平台打开场景后界面如下&#xff1a; 解题思路 看到此类的题目&#xff0c;应该和存储型xss有关&#xff0c;也就是将恶意代码保存到服务器端即然在服务器端&#xff0c;那就…

【Cocos入门】场景切换(loadScene、preloadScene)

一、loadScene 加载场景 loadScene(sceneName: string, onLaunched: Director.OnSceneLaunched, onUnloaded: Director.OnUnload) : boolean 通过场景名称进行加载场景。返回值为布尔类型 参数&#xff1a; NameTypeDescriptionsceneNamestring场景名称onLaunchedDirector.O…

基于Chrome插件的Chatgpt对话无损导出markdown格式(Typora完美显示)

刚刚提交插件到Chrome插件商店正在审核&#xff0c;想尝试的可以先使用&#xff1a; https://github.com/thisisbaiy/ChatGPT-To-Markdown-google-plugin/tree/main 我将源代码上传至了GitHub&#xff0c;欢迎star, IssueGoogle插件名称为&#xff1a;ChatGPT to MarkDown plus…

3.1 Verilog 连续赋值

关键词&#xff1a;assign&#xff0c; 全加器 连续赋值语句是 Verilog 数据流建模的基本语句&#xff0c;用于对 wire 型变量进行赋值。&#xff1a; 格式如下 assign LHS_target RHS_expression &#xff1b; LHS&#xff08;left hand side&#xff09; 指赋值操作…

C#委托的前世今生

起因 很多C#初学者&#xff0c;都遇到过这样的问题——线程间操作无效&#xff0c;从不是创建控件的线程访问它。 今天就这个问题&#xff0c;展开分析。 溯源 先说下这个问题产生的根源。 大家都知道&#xff0c;程序运行起来之后&#xff0c;首先会有一个主线程&#xff…

中小型网络系统总体规划与设计方法

目录 1.基于网络的信息系统基本结构 2.网络需求调研与系统设计原则 3.网络用户调查 4.网络节点地理位置分布情况 5.网络需求详细分析 6.应用概要分析 7.网络工程设计总体目标与设计原则 8.网络结构与拓扑构型设计方法 9.核心层网络结构设计 10.接入核心路由器 11.汇聚…

Android 环境搭建

1、桥接工具安装 网站地址&#xff1a;AndroidDevTools - Android开发工具 Android SDK下载 Android Studio下载 Gradle下载 SDK Tools下载 使用安装包&#xff1a; adb 查看当前链接成功的设备&#xff1a;adb devices 使用adb shell指令来进入到手机的后台&#xff1a;

Redis 持久化对性能有何影响?

Redis 持久化对性能的影响 Redis 是一个高性能的内存数据存储系统&#xff0c;通常被用于缓存、消息队列和数据存储等方面。由于 Redis 是基于内存的&#xff0c;因此它的读写速度非常快&#xff0c;可以满足高并发、低延迟的应用需求。但是&#xff0c;当 Redis 需要持久化数…

探索STM32CubeMX:图形化工具简化嵌入式软件开发

STM32CubeMX是由STMicroelectronics提供的一款图形化工具&#xff0c;旨在简化STM32微控制器的嵌入式软件开发过程。它提供了一种快速、直观的方式来生成初始化代码并配置STM32微控制器&#xff0c;帮助开发人员节省宝贵的开发时间&#xff0c;并降低入门门槛。本文将探索STM32…

政安晨:快速学会~机器学习的Pandas数据技能(四)(汇总与映射)

从数据中提取价值&#xff01; 概述 在上一篇文章中&#xff0c;我们学习了如何从DataFrame或Series中选择相关数据。从我们的数据表示中选择正确的数据对于完成工作非常重要&#xff0c;正如我们在练习中所演示的那样。 然而&#xff0c;数据并不总是以我们想要的格式直接从…

【力扣】两数之和,暴力枚举 + 哈希表

两数之和原题地址 方法一&#xff1a;暴力枚举 首先&#xff0c;我们需要枚举数组中所有可能的下标对组合&#xff0c;对于 n 个数的数组&#xff0c;从中选两个下标&#xff0c;有 种可能。做法很简单&#xff0c;遍历数组中的所有元素&#xff0c;对于每一个元素&#xff…