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://xiahunao.cn/news/2774050.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

以“防方视角”观JS文件信息泄露

为方便您的阅读&#xff0c;可点击下方蓝色字体&#xff0c;进行跳转↓↓↓ 01 案例概述02 攻击路径03 防方思路 01 案例概述 这篇文章来自微信公众号“黑白之道”&#xff0c;记录的某师傅从js文件泄露接口信息&#xff0c;未授权获取大量敏感信息以及通过逻辑漏洞登录管理员账…

docker安装-centos

Docker CE 支持 64 位版本 CentOS 7&#xff0c;并且要求内核版本不低于 3.10 卸载旧版本Docker sudo yum remove docker \ docker-common \ docker-selinux \ docker-engine使用yum安装 yum 更新到最新版本: sudo yum update执行以下命令安装依赖包&#xff1a; sudo yum…

e5 服务器具备哪些性能特点?

随着云计算和大数据技术的不断发展&#xff0c;服务器作为数据中心的核心设备&#xff0c;其性能特点也日益受到关注。其中&#xff0c;E5服务器作为当前主流的服务器类型之一&#xff0c;具备许多优秀的性能特点。本文将详细介绍E5服务器的性能特点&#xff0c;帮助读者更好地…

day7(2024/2/8)

mainui.h(第二个界面) #ifndef MAINUI_H #define MAINUI_H#include <QWidget>namespace Ui { class MainUi; }class MainUi : public QWidget {Q_OBJECTpublic:explicit MainUi(QWidget *parent nullptr);~MainUi();public slots:void main_ui();private:Ui::MainUi *u…

人工智能基础部分24-人工智能的数学基础,汇集了人工智能数学知识最全面的概况

、 大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能基础部分24-人工智能的数学基础&#xff0c;汇集了人工智能数学知识最全面的概况&#xff0c;深度学习是一种利用多层神经网络对数据进行特征学习和表示学习的机器学习方法。要全面了解深度学习的数学基…

Spark安装(Yarn模式)

一、解压 链接&#xff1a;https://pan.baidu.com/s/1O8u1SEuLOQv2Yietea_Uxg 提取码&#xff1a;mb4h tar -zxvf /opt/software/spark-3.0.3-bin-hadoop3.2.tgz -C /opt/module/spark-yarn mv spark-3.0.3-bin-hadoop3.2/ spark-yarn 二、配置环境变量 vim /etc/profile…

VTK 体渲染设置帧率

当我们的mapper采样距离设置较低或者硬件性能不太好时&#xff0c;体渲染交互会有卡顿现象。为了提高交互时的流畅性&#xff0c;可以设置交互器的SetDesiredUpdateRate来降低采样率进而避免卡顿现象。 vtkNew<vtkRenderWindowInteractor> iren; iren->SetDesiredUpd…

WordPress如何实现随机显示一句话经典语录?怎么添加到评论框中?

我们在一些WordPress网站的顶部或侧边栏或评论框中&#xff0c;经常看到会随机显示一句经典语录&#xff0c;他们是怎么实现的呢&#xff1f; 其实&#xff0c;boke112百科前面跟大家分享的『WordPress集成一言&#xff08;Hitokoto&#xff09;API经典语句功能』一文中就提供…

Unity类银河恶魔城学习记录4-4 4-5 P57-58 On Hit Impactp- Attack‘direction fix源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili Entity.cs using System.Collections; using System.Collections.Generic;…

【操作系统】MacOS虚拟内存统计指标

目录 命令及其结果 参数解读 有趣的实验 在 macOS 系统中&#xff0c;虚拟内存统计指标提供了对系统内存使用情况和虚拟内存操作的重要洞察。通过分析这些指标&#xff0c;我们可以更好地了解系统的性能状况和内存管理情况。 命令及其结果 >>> vm_stat Mach Virtu…

Qt程序设计-读写CSV文件

本文实例演示Qt读写CSV文件实现 创建项目 添加两个按钮和一个显示路径的label 界面如下 UI界面 <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"><class>MainWindow</class><widget class="QM…

Redis篇之集群

一、主从复制 1.实现主从作用 单节点Redis的并发能力是有上限的&#xff0c;要进一步提高Redis的并发能力&#xff0c;就需要搭建主从集群&#xff0c;实现读写分离。主节点用来写的操作&#xff0c;从节点用来读操作&#xff0c;并且主节点发生写操作后&#xff0c;会把数据同…

年货大数据(电商平台年货节数据):水果销售额增长72%,海鲜肉类涨幅高于蔬菜

春节临近&#xff0c;生鲜又成了线上线下“叫卖”狠&#xff0c;竞争大&#xff0c;盈利好的行业之一。无论是线下商超&#xff0c;还是线上电商&#xff0c;生鲜行业在年货节期间不愁没有市场需求。 根据鲸参谋数据显示&#xff0c;1月前三周京东平台生鲜市场整体销量超3300万…

yt-dlp快速上手

之前用xx下载视频经常遇到网络报错&#xff0c;于是使用 yt-dlp 这个新的yt下载工具。 安装教程 安装方法1&#xff1a;pip安装 可以使用pip安装yt-dlp&#xff0c;然后可以全局使用 使用pip快速安装如下: python3 -m pip install -U yt-dlp不安装其他依赖的安装命令如下:…

npm 上传一个自己的应用(4) 更新自己上传到NPM中的工具版本 并进行内容修改

前面 npm 上传一个自己的应用(2) 创建一个JavaScript函数 并发布到NPM 我们讲了将自己写的一个函数发送到npm上 那么 如果我们想到更好的方案 希望对这个方法进行修改呢&#xff1f; 比如 我们这里加一个方法 首先 我们还是要登录npm npm login然后 根据要求填写 Username 用…

【doghead】VS2022 win11 安装配置WSL2 以编译linux端的cmake项目并运行1

Visual Studio 2022 在Windows上编译调试WSL2 CMake Linux工程 好像是我自己的vs2022的一个插件支持rust https://github.com/kitamstudios/rust-analyzer.vs/blob/master/PREREQUISITES.md Latest rustup (Rust Toolchain Installer). Install from here. Welcome to Rust!Th…

【前端web入门第五天】01 结构伪类选择器与伪元素选择器

文章目录: 1.结构伪类选择器 1.1 nth-child(公式) 2.伪元素选择器 1.结构伪类选择器 作用:根据元素的结构关系查找元素。 选择器说明E:first-child查找第一个E元素E:last-child查找最后一个E元素E:nth-child(N)查找第N个E元素&#xff08;第一个元素N值为1) 一个列表结构…

Vue前端框架--Vue工程项目问题总结{脚手架 Vue-cli}

Vue脚手架部署问题总结 我所遇到的一共两大问题 只有先执行npm install之后 才能run serve 否则会报错 vue-cli-serve不是内部或者外部的命令&#xff0c;也不是可运行的程序或者批处理文件的错误 1. 运行npm install会报错 2. 运行npm run serve报错 nodejs官网为 https://no…

【动态规划】【前缀和】【C++算法】LCP 57. 打地鼠

作者推荐 视频算法专题 本文涉及知识点 动态规划汇总 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 LCP 57. 打地鼠 勇者面前有一个大小为3*3 的打地鼠游戏机&#xff0c;地鼠将随机出现在各个位置&#xff0c;moles[i] [t,x,y] 表…

【Git版本控制 04】标签管理

目录 一、创建标签 二、查看标签 三、推送标签 四、删除标签 一、创建标签 标签tag&#xff0c;是对某次 commit 的⼀个标识&#xff0c;相当于起了⼀个别名。 相较于难以记住的 commit id &#xff0c; tag 很好的解决这个问题&#xff0c;因为 tag ⼀定要给⼀个让⼈容易…