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.hqwc.cn/news/459922.html

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

相关文章

STM32——LCD(1)认识

目录 一、初识LCD 1. LCD介绍 2. 显示器的分类 3. 像素 4. LED和OLED显示器 5. 显示器的基本参数 &#xff08;1&#xff09;像素 &#xff08;2&#xff09;分辨率 &#xff08;3&#xff09;色彩深度 &#xff08;4&#xff09;显示器尺寸 &#xff08;5&#xff…

免费领取阿里云学生专享服务器和300元无门槛代金券

阿里云学生服务器优惠活动&#xff1a;高效计划&#xff0c;可以免费领取一台阿里云服务器&#xff0c;如果你是一名高校学生&#xff0c;想搭建一个linux学习环境、git代码托管服务器&#xff0c;或者创建个人博客网站记录自己的学习成长历程&#xff0c;拥有一台云服务器是很…

Unity3d Shader篇(五)— Phong片元高光反射着色器

文章目录 前言一、Phong片元高光反射着色器是什么&#xff1f;1. Phong片元高光反射着色器的工作原理2. Phong片元高光反射着色器的优缺点优点缺点 二、使用步骤1. Shader 属性定义2. SubShader 设置3. 渲染 Pass4. 定义结构体和顶点着色器函数5. 片元着色器函数 三、效果四、总…

邮箱营销软件推荐?企业邮箱群发会限制吗?

邮箱营销平台怎么选择&#xff1f;哪种邮箱适合做外贸邮件群发&#xff1f; 邮箱营销凭借其精准触达、低成本和高回报的特点&#xff0c;依然是许多企业不可或缺的营销手段。该如何选择一款适合自己的工具呢&#xff1f;蜂邮EDM将为您推荐几款优秀的邮箱营销软件&#xff0c;并…

【Git】08 多人单分支协作场景

文章目录 一、场景1&#xff1a;不同人修改不同文件1.1 场景描述1.2 场景复现1.2.1 克隆到本地1.2.2 新建分支1.2.3 B修改、提交与推送1.2.4 A修改与提交1.2.5 B再次修改并推送1.2.6 A推送报错 1.3 解决 二、场景2&#xff1a;不同人修改同文件的不同区域2.1 场景描述2.2 场景复…

代码随想录算法训练营第30天| 51. N皇后、总结

51. N皇后 完成 思路&#xff1a; 如何用回溯法搜索二维棋盘是这道题目和之前不一样的地方&#xff0c;也是题目的难点。 在树形结构中&#xff0c;同层取同一行棋盘的不同列遍历。每递归一次就往下遍历一行。 代码 class Solution {List<List<String>> res n…

Pytorch+NCCL源码编译

目录 环境1. 安装cudnn2. 使用pytorch自带NCCL库进行编译3. 修改NCCL源代码并重新编译后测试&#xff0c;体现出源码更改 环境 Ubuntu 22.04.3 LTS (GNU/Linux 5.15.0-91-generic x86_64)cuda 11.8 cudnn 8python 3.10torch V2.0.1 nccl 2.14.3NVIDIA GeForce RTX 4090 *2 1.…

疑似针对安全研究人员的窃密与勒索

前言 笔者在某国外开源样本沙箱平台闲逛的时候&#xff0c;发现了一个有趣的样本&#xff0c;该样本伪装成安全研究人员经常使用的某个渗透测试工具的破解版压缩包&#xff0c;对安全研究人员进行窃密与勒索双重攻击&#xff0c;这种双重攻击的方式也是勒索病毒黑客组织常用的…

python入门篇11-面向对象的基础使用

全文目录,一步到位 1.前言简介1.1 专栏传送门1.1.1 上文小总结1.1.2 上文传送门 2. python基础使用2.1 面向对象的基础使用2.1.1 创建类2.1.2 使用对象(定义成员变量)2.1.3 成员方法的定义与使用2.1.4 构造方法的使用2.1.5 常用魔术方法 2.2 面向对象思想核心2.2.1 面向对象_私…

【知识整理】管理即服务,识人、识己

1. 背景 一个人的力量是有限的&#xff0c;如何规模化生产&#xff0c;人员的规模化组织&#xff0c;如何提升合作的规模和效率。 管理的本质&#xff1a; 1、服务他人&#xff1f; 2、激发主动性&#xff1f; 3、氛围宽松&#xff1f; 上面是理念&#xff0c; 1、那如何…

006集——where语句进行属性筛选——arcgis

在arcgis中&#xff0c; dBASE 文件除了 WHERE 语句以外&#xff0c;不支持 其它 SQL 命令。选择窗口如下&#xff1a; 首先&#xff0c;我们了解下什么是where语句。 WHERE语句是SQL语言中使用频率很高的一种语句。它的作用是从数据库表中选择一些特定的记录行来进行操作。WHE…

Spring Cloud使用ZooKeeper作为注册中心的示例

简单的Spring Cloud应用程序使用ZooKeeper作为注册中心的示例&#xff1a; 1.新建模块&#xff1a; 2.勾选依赖&#xff1a; 3.在pom.xml文件中做出部分修改及添加Spring Cloud Zookeeper 依赖版本&#xff1a; 完整pom文件 <?xml version"1.0" encoding&q…