← 返回文章流

Redis 八股.md

# Redis 八股 > 参考文档:https://javaguide.cn/database/redis/redis-questions-01.html ## 为什么用 redis - 内存,快 redis基于内存,访问速度比将数据放置在磁盘的数据库更快,对于高频访问的公共数据放在redis中,下次直接从内存中读取,访问速度更快 在程序猿进阶服务站项目中,redis 存放了系统推荐数据和用户名列表数据,由于程序猿进阶服务站并未强制登录,在没有登录的情况下仍可访问项目,我们的推荐系统对没有登录的推荐数据进行了兜底,此时redis便存放了这个公共数据;对于用户名列表,由于系统设计时需保证用户名唯一,我们也将该数据放置在了redis中 ## redis 常用的数据类型有哪些? - string - list - set - Zset 【后续确认】在程序猿进阶服务站项目中,主要用到了 list 和 Zset,其中 list存放用户名,Zset存放系统推荐数据,由于系统推荐数据是基于推荐系统的得分进行推荐,每份数据都有一个得分,根据得分进行降序排序 ## Redis 给缓存数据设置过期时间有什么用 由于 redis 是基于内存的,内存有限且珍贵,如果不对缓存的数据设置过期时间,那么内存占用就会一直增长,最终可能导致OOM问题 ## Redis 过期 key 删除策略了解么? 常见的过期数据删除策略有以下几种: 1. 惰性删除:只有访问该key时才对数据进行过期检查,若已过期则进行删除,但是可能造成太多过期key没有被删除 2. 定期删除:周期性地随机从设置了过期时间的key中抽查一部分,然后逐个检查这些key是否过期,过期则进行删除,相比于惰性删除,定期删除对内存更友好 其中,Redis 采用的便是 **定期删除+惰性删除** 组合的策略 ## 大key问题 当 redis 中存在大量 key 在同一时间点集中过期时,可能导致以下问题: - CPU占用率升高,请求延迟增加:redis 在处理过期 key 时需要消耗CPU资源,如果过期key数量庞大,会导致redis实例的CPU占用率高,进而影响其它请求的速度,造成延迟增加 - 内存占用过高:过期的key虽然已经失效,但在redis真正删除它们之前,仍然会占用内存,如果过期的key没有及时清理,可能会导致内存占用过高 大 key 问题的常见解决方案有: 1. 尽量避免 key 集中过期:在设置key的过期时间时可以在指定范围内随机一点 2. 异步删除:可以在redis的配置文件中开启,lazy-free 机制,设置为 yes,进行异步删除过期的key ## Redis 持久化:RDB、AOF 由于 redis 是基于内存,而内存在断电或者其它故障时是不会保存数据的,持久化策略只能围绕磁盘实现,RDB与AOF两种策略的区别是: - RDB:隔一段时间将数据持久化到磁盘中 - AOF:与MySql类似,持久化的是操作,如:增加操作、修改操作、删除操作,通过这些操作即可还原数据 ### RDB > 类似于我的博客备份网站,默认情况下只有进行构建时才会触发备份,在后续时间内修改、删除、增加文章时,备份的数据都不会变化 在配置的时间间隔内,将内存中的数据写入磁盘中,缺点是数据容易丢失,在时间间隔内数据发生了变化,此时还没有持久化,若此时发生故障,数据会丢失 - 缺点:数据容易丢失(按时间间隔持久化,下一个周期到达时发生故障,只持久化当前周期的数据) - 优点:数据恢复速度快 ### AOF RDB是记录实际数据,而AOF则记录数据更改相关命令,通过执行命令来恢复数据,数据丢失少 AOF重写,由于AOF记录的是操作,当文件过大时,生成一个压缩后的AOF文件 - 优点:数据丢失少 - 缺点:恢复速度慢 ## Redis 分布式锁 当多个请求同一时间请求同一个资源时,需对该资源加锁,否则可能出现资源异常,对于单点服务只需后端添加一个同步锁即可,但是,若后端服务是集群的,此时同步锁的作用范围只有当前服务器,此时同步锁无法约束其它服务器,但资源仍需要进行加锁,此时可以考虑实现redis 分布式锁,通过 SETNX 即可进行处理 > 在 Redis 中,`SETNX` 命令可以帮助我们实现互斥。`SETNX` 即 **SET** if **N**ot e**X**ists(对应 Java 中的 `setIfAbsent` 方法),如果 key 不存在的话,才会设置 key 的值。如果 key 已经存在,`SETNX` 啥也不做。 > > ```bash > > SETNX lockKey uniqueValue > (integer) 1 > > SETNX lockKey uniqueValue > (integer) 0 > ``` > > 释放锁的话,直接通过 `DEL` 命令删除对应的 key 即可。 > > ```bash > > DEL lockKey > (integer) 1 > ``` ## 模拟面试 总结: - redis 基于内存 - redis的单线程指的是什么?——redis 的命令由主线程串行处理 - redis的del删除命令是:同步删除命令,大量删除时redis主线程会卡顿,建议使用异步删除命令 unlink - 大key:单个key对应的value包含大量数据 ### 1.Redis 是什么?在 Java 后端系统中,为什么会使用 Redis? redis是基于内存的键值数据存储系统,相较于传统的磁盘数据库,速度更快,因此对于java后端系统中,可以将公共数据放置在redis中,提高访问性能,并减轻如MySQL数据库的压力 ### 2. 除了数据主要存储在内存中,Redis 速度快还有哪些原因? > 不推荐下面的回答 - redis:单线程 - redis 提供多种数据结构,并且redis底层为每种数据类型的实现进行了优化 除了数据主要存储在内存中,Redis 速度快还有两个重要原因: 首先,Redis 的核心命令执行主要采用单线程模型。单线程可以避免多线程之间频繁的上下文切换,同时也减少了多个线程访问共享数据时的锁竞争,因此 Redis 执行命令的过程比较简单高效 其次,redis还提供了多种数据结构,并且每种数据结构redis的底层实现做了优化,不过对于详细的底层实现我并不了解 > ==为了避免下述情况:== > > ==面试问你redis问什么快,后面估计还会问为什么单线程还会怎么快,为什么redis6 使用多线程,什么是多路复用?等一连串追问== 最终版回答是: 除了存储于内存外,redis还提供了多种数据结构,并且每种数据结构redis的底层实现做了优化,不过对于详细的底层实现我并不了解 > 这个回答部分正确,但不够完整。 > > 但为了避免后续的一连串不会的追问,损失一点感觉还好 ### 3. 经常有人说“Redis 是单线程的”,这里的“单线程”具体指什么?既然是单线程,它为什么还能处理大量请求? > 我的回答:redis的核心命令是由一个线程完成,由于redis使用了IO多路复用,可以处理大量请求 “单线程”主要指 Redis 的命令执行过程通常由主线程串行完成,并不代表 Redis 的所有工作都只有一个线程,例如持久化、异步释放内存等可能由后台线程或子进程处理。此外,新版本 Redis 也可以使用 I/O 线程辅助处理网络读写。 ### 4. 请你说明 I/O 多路复用在 Redis 中大致是怎样工作的,以及它为什么能让一个主线程同时处理大量客户端连接? ### 5. 如果某个客户端对一个包含大量元素的 Key 执行耗时很长的命令,会对其他客户端请求产生什么影响?为什么? > CPU占用率升高,其它请求响应速度变慢,由于redis基于内存,大量元素的key占据内存空间,而且对此进行操作时,会占用CPU,其它请求响应变慢 回答方向基本正确,但因果关系需要更准确。 其他请求变慢的直接原因不是“大 Key 占用了较多内存”,而是对大 Key 执行某些命令时需要遍历或处理大量元素,命令执行时间较长。==由于命令主要由主线程串行执行==,在这条命令完成前,后续请求只能等待。CPU 占用升高可能同时出现,但也不是所有情况下都会明显升高。 继续追问:如果需要删除一个包含大量元素的大 Key,直接执行 `DEL` 可能有什么问题?你会如何降低它对线上请求的影响? ### 6. 如果需要删除一个包含大量元素的大 Key,直接执行 `DEL` 可能有什么问题?你会如何降低它对线上请求的影响? DEL 是同步删除命令,对于大量删除可能导致redis主线程卡顿,降低响应可以考虑: 1. 使用异步删除 unlink 2. 大key可使用随机过期时间,进行数据清理 ### 7. 请你区分“大 Key”和“大量 Key 集中过期”这两个问题,并分别说明它们可能给 Redis 带来的主要影响。 - 大 Key 是单个 Key 对应的 value 过大或包含的元素过多。除了占用较多内存,对它执行全量读取、遍历、删除等操作,也可能造成主线程阻塞或网络传输压力。 - 大量 Key 集中过期是许多独立的 Key 在相近时间失效。过期清理可能增加 Redis 的 CPU 开销,但影响不只发生在 Redis 内部。 ### 8. 如果大量热点 Key 在同一时刻过期,从 Java 服务、Redis 到 MySQL,可能出现怎样的连锁反应? Key 过期后会被视为不存在,因此缓存不会继续命中。大量请求会同时绕过 Redis 访问 MySQL,可能导致数据库连接数、CPU 或查询负载激增,产生缓存雪崩。 ### 9. 针对这种缓存雪崩,你会从缓存过期策略和系统保护两个层面采取哪些措施? 过期策略: - 比见面大量key的过期时间一致,可以在过期时间上增加随机时间,让失效时间分散 系统保护层面,核心目标是:即使缓存大量失效,也要限制进入 MySQL 的请求规模,例如限流、降级或熔断,避免故障继续扩散。 ### 10. 假设一个热点 Key 刚好过期,此时有 1000 个并发请求同时查询它,你会如何避免这 1000 个请求全部访问 MySQL?

作者:Tilex作者主页
在原博客阅读全文 (新标签页打开)

以上内容来自博客订阅源,版权归原作者。关注作者后可以在 关注列表 第一时间查看作者文章。

一起聊聊 0

尊重不同观点

还没有评论。欢迎分享第一个想法。

RSS SUBSCRIPTIONS

选择 RSS 订阅

把博客汇的文章添加到你常用的阅读器。

关注文章 RSS 订阅本订阅需要登录后使用