Redis缓存知识点汇总

devtools/2025/1/1 1:39:15/

Redis缓存知识点汇总

请先思考如下问题
1.Redis的缓存击穿,穿透,雪崩是什么意思?原因和解决方案有哪些?
2.Redis支持宕机数据恢复,他的持久化方式及其原理是什么?
3.如何保证双写一致性,即如何保证Redis缓存与数据库的数据一致性?
4.Redis如何实现缓存过期删除?淘汰策略都有哪些?
5.Redis如何实现分布式锁,可重入锁?锁超时,但是业务还没执行完怎么办?
6.Redisson的看门狗机制?
7.Redis为什么那么快?单线程,多路复用?为什么不使用多线程。

1.缓存穿透

原因:Redis缓存穿透是指在高并发场景下,大量请求同时查询一个不存在的数据,这些请求会直接穿透Redis缓存,进而查询数据库,导致数据库压力过大,甚至可能崩溃。这种情况通常发生在缓存中没有命中数据,而数据库中也没有对应的数据,属于恶意访问场景。
解决
1.布隆过滤器:使用布隆过滤器来预先判断数据库是否存在相应的数据。
2.缓存空值:查询结果后若数据库没有值,则缓存空值到redis中,就不会击穿到数据库中。

布隆过滤器: 布隆过滤器的工作原理基于以下几个步骤:
初始化
创建一个大小为m的位数组,初始时所有位都设置为0。同时选择多个不同的哈希函数,这些哈希函数可以将元素映射到位数组中的一个位置。
插入元素
当要插入一个元素时,使用这k个哈希函数计算出k个不同的位位置,并将这些位置的值设置为1。
查询元素
当要查询一个元素是否在集合中时,同样使用这k个哈希函数计算出k个位位置,检查这些位置是否都为1。如果所有位置都为1,则认为元素可能在集合中;如果任一位置为0,则元素一定不在集合中。在这里插入图片描述

1.布隆过滤器为什么使用多个hash函数来计算?
答:利用多个hash函数计算的结果拼接在一起,唯一性更大,能减小hash冲突的概率,从而减小误报的概率。
2.如何确定布隆过滤器位数组的大小?
答:根据预先插入的数据个数以及能接受的误报率 再利用公式计算可得到数组大小。

2. 缓存击穿

原因缓存击穿是指当某个热点数据(通常是访问频率极高的数据)在缓存中失效时,大量的请求同时到达,导致这些请求都直接查询数据库,从而对数据库造成巨大的压力,甚至可能导致数据库服务不可用的情况,属于用户正常的请求场景,非恶意访问。
解决
1.分布式锁:使用分布式锁来保证同一时刻只有一个请求到达数据库。
2.逻辑过期:热点数据设置永不过期,额外添加一个过期时间字段,查询的时候发现数据过期需要重建缓存

3. 缓存雪崩

原因:大量的缓存在同一时间过期,导致请求击穿到数据库。
解决:给不同的key设置随机的时效时间。

缓存问题的保底策略,分布式锁,限流降级,集群

4. Redis如何保证与数据库的数据一致性

原因:修改了数据库,如何保证数据库和缓存的数据一致性。
解决
1.延时双删:多线程场景下,不论是先删除缓存,再修改数据库,还是先修改数据库再删除缓存都不可行,因为这些操作不是原子性操作,在多线程切换的时候很容易会造成数据不一致的情况。如果不需要保证强一致性,最优解决办法就是延迟双删策略,先删除缓存,再修改数据库,再等一会儿删除缓存。但延时双删也不能完全保证数据一致性,因为最后一次删除缓存的时间并不能保证一定在其他线程写入缓存之后。
2.分布式锁:分布式锁可以保证强一致性,缓存的删除,写入与数据库修改满足原子性,不受线程切换的影响。

如何更新redis缓存
弱一致性:可参考阿里的canal中间件的实现,伪装成mysql的一个从节点,通过监听sql的binlog日志来更新缓存
强一致性:redission的读写锁来处理数据库修改和缓存的更新
在这里插入图片描述

5. Redis如何持久化

原因redis意外宕机后,需要有缓存恢复机制,一定频率的持久化机制保证了数据不会丢失。
解决
1.RDBredis执行bgsave指令时,会fork一个子进程(不是线程)通过页表(linux不允许直接操作物理内存,页表是虚拟内存和物理内存的映射关系表)共享内存,按照一定的频率,将内存中的缓存数据同步到磁盘备份文件中。如果主进程此时有写操作,主进程利用copy-on-write复制一份页表,基于副本做修改,不影响子进程的页表读取。持久化过程中,主进程的读请求是在副本上完成。
在这里插入图片描述2.AOFredis会记录每一条redis命令,然后存储到AOF文件中,类似mysql的binlog日志文件。但一条数据的指令可能会有很多条,只有其中几个是必要的。此策略需要设置存储指令的频率,设置太高影响性能,设置太低会造成一定时间内的数据丢失。还需要设置压缩频率,要不然文件会越来越大。

如何选择持久化模式?
rdb占用体积小,恢复速度快,但是宕机会丢失更多的数据。io读写导致不能做到实现每秒备份一次。
aof占用体积大,恢复速度慢,但几乎秒级的备份机制几乎可以做到不丢失数据。
如果业务对数据安全性要求较高,可以使用AOF+RDB。如果业务容对数据丢失忍度较高,对性能要求较高,建议使用RDB。

6. 数据过期策略

redis采用“惰性删除”+“定时删除”策略。
问:key过期后会立马进行删除吗?
答:不会,惰性删除和定时删除同时启用,但还要看设置的定时删除策略中的频率配置。
1.惰性删除:查询请求过来的时候,才对过期的key进行删除。会导致一直没有查询某个key的时候,缓存没删除,内存一直被占用。
2.定时删除:定时的扫描删除过期的key,slow模式每100ms执行一次,每次清理时间不超25ms。fast模式每2ms执行一次,每次清理时间不超1ms。
10. 数据淘汰策略
原因:当redis内存不够时,需要清除掉一部分缓存,来让新缓存添加进来。
解决
1.allkeys-lru:所有缓存,最近一次使用时间最远的将被淘汰掉。
2.volatiel-lru:设置了过期时间的缓存,最近一次使用时间最远的将被淘汰掉。
3.allkeys-lfu:所有缓存,使用频率最低的将被淘汰掉。
4.volatiel-lfu:设置了过期时间的缓存,使用频率最低的将被淘汰掉。
5.noevcatino:不淘汰,拒绝添加新缓存
6.allkeys-random:所有缓存随机淘汰
7.volatiel-random:设置了ttl过期时间的缓存,随机淘汰。
8.valatiel-ttl:设置了ttl过期时间的缓存,剩余缓存时间最小的淘汰。

7. Redis实现分布式锁的原理

在这里插入图片描述
业务开始时,利用redis的set nx指令来添加锁,业务结束时,利用del指令来删除锁,达到了分布式锁的效果。
但如果不设置超时时间,服务宕机就会一直锁住得不到释放。所以需要添加锁的过期时间。
过期时间不好预估,添加过期时间之后,有可能业务才执行一半就过期了,会造成数据问题。如果主线程一直没有主动释放锁,说明业务还未结束,需要有个线程来不断的给主线程自动续期。续期逻辑是先判断锁是否存在,如果不存在说明业务执行完解锁了,结束子线程。如果存在且还有1/3的时间即将超期,则会使用set nx再次续期。
redission客户端就帮我们实现了这个功能,他是用set key value nx time 指令来实现如果缓存中不存在key,则添加key,并设置过期时间。然后利用看门狗机制,保证业务执行超时的时候锁会自动续期,不至于执行一半超时解锁。主要原理是,redisson在添加锁的时候,会另起一个线程来监控添加锁的那个主线程是否结束,如果结束的话就释放锁,如果没结束,但是马上超期了,就利用set nx指令来自动续期。

8. Redisson的可重入锁如何实现?

基于Redis实现的分布式锁,它允许同一个线程在不释放锁的情况下多次获得锁,并在所有锁操作完成后,锁才真正被释放。以下是Redisson可重入锁实现的主要原理:
在这里插入图片描述

使用Hash结构:Redisson使用Redis的Hash数据结构来存储锁的信息。其中,key表示锁的名称,field标识线程的持有者(通常是线程ID),value为锁的重入次数。

锁的获取:当一个线程尝试获取锁时,Redisson会使用Lua脚本来保证操作的原子性。如果锁不存在(即Redis中没有对应的key),则创建一个新的锁,并设置重入次数为1。如果锁已经存在,并且当前线程是锁的持有者,则增加重入次数。

锁的释放:当线程完成操作并释放锁时,Redisson会减少锁的重入次数。只有当重入次数减至0时,锁才会真正被释放。

锁的过期时间:在获取锁的同时,Redisson会为锁设置一个过期时间,以避免死锁的发生。如果锁在一定时间内没有被释放,它将自动过期并被删除。

自动续期:Redisson还提供了看门狗机制,它会在锁的过期时间到达之前自动续期,确保锁不会因为过期而被意外释放。

线程安全:在释放锁时,Redisson会检查Redis中存储的线程ID与当前线程的ID是否匹配,确保只有锁的持有者才能释放锁。

通过这些机制,Redisson实现了一个可重入的分布式锁,允许同一个线程多次获取和释放锁,同时保证了锁的安全性和可靠性。


http://www.ppmy.cn/devtools/146414.html

相关文章

深入了解SpringIoc(续篇)

目录 注入 Bean 的方式有哪些? 构造函数注入还是 Setter 注入? Bean 的作用域有哪些? Bean 是线程安全的吗? Bean 的生命周期了解么? 注入 Bean 的方式有哪些? 依赖注入 (Dependency Injection, DI) 的常见方式: 构造函数注入:通过类的构造函…

数学建模 绘图 图表 可视化(2)

文章目录 前言柱形图条形图克利夫兰点图系列坡度图南丁格尔玫瑰图径向柱图极坐标图词云图总结参考资料 前言 承接上期 数学建模 绘图 图表 可视化(1)的总体描述,这期我们继续跟随《Python 数据可视化之美 专业图表绘制指南》步伐来学习其中l…

从虚拟到现实:AI与AR/VR技术如何改变体验经济?

引言:体验经济的崛起 在当今消费环境中,产品与服务早已不再是市场竞争的唯一焦点,能够提供深刻感知和独特体验的品牌,往往更能赢得消费者的青睐。这种转变标志着体验经济的崛起。体验经济不仅仅是简单的买卖行为,而是通…

VLM和VLAM(VLA)相关介绍和发展历程

目录 一、个人感想二、相关介绍2.1 视觉语言模型 (VLM) 的发展历程2.2 视觉语言动作模型 (VLA) 的发展历程2.3 一些关键的研究工作:一些架构图 三、发展历程3.1 视觉语言模型 (VLM) 的发展时间线3.2 视觉语言动作模型 (VLA) 的发展时间线 四、参考资料 一、个人感想…

github codespaces推送镜像时unauthorized: access token has insufficient scopes 解决方法

最近有镜像构建的需求,于是就使用了github提供的这个codespace来构建docker镜像,但是在构建后进行镜像推送时提示 unauthorized: access token has insufficient scopes ,如下图 这个一看就知道是权限问题, 这里的access token h…

PDF书籍《手写调用链监控APM系统-Java版》第2章 第一个Agent应用

本人阅读了 Skywalking 的大部分核心代码,也了解了相关的文献,对此深有感悟,特此借助巨人的思想自己手动用JAVA语言实现了一个 “调用链监控APM” 系统。本书采用边讲解实现原理边编写代码的方式,看本书时一定要跟着敲代码。 作者…

【从0带做】基于Springboot3+Vue3的场馆预约系统

大家好,我是武哥,最近给大家手撸了一个基于SpringBoot3Vue3的场馆预约系统,可用于毕业设计、课程设计、练手学习,系统全部原创,如有遇到网上抄袭站长的,欢迎联系博主~ 项目演示视频和教程视频 https://ww…

FlaskAPI-路径参数、查询参数

1 路径参数 在 Flask 中,路径传参是一种常见的传递数据的方式。通过在 URL 路径中指定参数,可以让视图函数根据不同的参数值来返回不同的内容。这种方式可以用于根据用户请求的不同资源(如用户 ID、产品编号等)来提供定制化的响应…