BATJ关于Redis的高频面试真题

降级的最终目的是保证核心服务可用,即使是有损的。而且有些服务是无法降级的(如加入购物车、结算)。

以参考日志级别设置预案:

(1)一般:比如有些服务偶尔因为网络抖动或者服务正在上线而超时,可以自动降级;

(2)警告:有些服务在一段时间内成功率有波动(如在95~100%之间),可以自动降级或人工降级,并发送告警;

(3)错误:比如可用率低于90%,或者数据库连接池被打爆了,或者访问量突然猛增到系统能承受的最大阀值,此时可以根据情况自动降级或者人工降级;

(4)严重错误:比如因为特殊原因数据错误了,此时需要紧急人工降级。

服务降级的目的,是为了防止Redis服务故障,导致数据库跟着一起发生雪崩问题。因此,对于不重要的缓存数据,可以采取服务降级策略,例如一个比较常见的做法就是,Redis出现问题,不去数据库查询,而是直接返回默认值给用户。


三、热点数据和冷数据是什么


1、热点数据,缓存才有价值

对于冷数据而言,大部分数据可能还没有再次访问到就已经被挤出内存,不仅占用内存,而且价值不高。

对于热点数据,比如我们的某IM产品,生日祝福模块,当天的寿星列表,缓存以后可能读取数十万次。

再举个例子,某导航产品,我们将导航信息,缓存以后可能读取数百万次。

2、数据更新前至少读取两次,缓存才有意义

这个是最基本的策略,如果缓存还没有起作用就失效了,那就没有太大价值了。

那存不存在,修改频率很高,但是又不得不考虑缓存的场景呢?有!比如,这个读取接口对数据库的压力很大,但是又是热点数据,这个时候就需要考虑通过缓存手段,减少数据库的压力,比如我们的某助手产品的,点赞数,收藏数,分享数等是非常典型的热点数据,但是又不断变化,此时就需要将数据同步保存到Redis缓存,减少数据库压力。


四、Memcache与Redis的区别都有哪些?


1、存储方式 Memecache把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小。Redis有部分存在硬盘上,redis可以持久化其数据。

2、数据支持类型 Memcache所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型 ,提供string,list,set,zset,hash等数据结构的存储。

3、使用底层模型不同。它们之间底层实现方式以及与客户端之间通信的应用协议不一样。Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。

4、 value 值大小不同:Redis 最大可以达到 1gb;memcache 只有 1mb。

5、Redis 的速度比Memcache快很多。

6、Redis支持数据的备份,即Master-Slave模式的数据备份。


五、单线程的redis为什么这么快


1、纯内存操作

2、单线程操作,避免了频繁的上下文切换

3、采用了非阻塞I/O多路复用机制


六、redis的数据类型,以及每种数据类型的使用场景


回答:一共五种。

1、String

这个其实没啥好说的,最常规的set/get操作,value可以是String也可以是数字。一般做一些复杂的计数功能的缓存。

2、hash

这里value存放的是结构化的对象,比较方便的就是操作其中的某个字段。博主在做单点登录的时候,就是用这种数据结构存储用户信息,以cookieId作为key,设置30分钟为缓存过期时间,能很好的模拟出类似session的效果。

3、list

使用List的数据结构,可以做简单的消息队列的功能。另外还有一个就是,可以利用lrange命令,做基于redis的分页功能,性能极佳,用户体验好。本人还用一个场景,很合适—取行情信息。就也是个生产者和消费者的场景。LIST可以很好的完成排队,先进先出的原则。

4、set

因为set堆放的是一堆不重复值的集合。所以可以做全局去重的功能。为什么不用JVM自带的Set进行去重?因为我们的系统一般都是集群部署,使用JVM自带的Set,比较麻烦,难道为了一个做一个全局去重,再起一个公共服务,太麻烦了。

另外,就是利用交集、并集、差集等操作,可以计算共同喜好,全部的喜好,自己独有的喜好等功能。

5、zset

zset是reids最有特色的数据结构,它类似于Java的SortedSet和HashMap的结合体。一方面它是个set,保证了内部value的唯一性,另一方面它可以给每个value赋予一个score,代表这个value的排序权重。内部实现是跳表,关于跳表感兴趣可以看下这篇文章:数据结构与算法分析:(十)跳表


七、redis的过期策略以及内存淘汰机制


redis采用的是定期删除+惰性删除策略

为什么不用定时删除策略?

定时删除,用一个定时器来负责监视key,过期则自动删除。虽然内存及时释放,但是十分消耗CPU资源。

在大并发请求下,CPU要将时间应用在处理请求,而不是删除key,因此没有采用这一策略。

定期删除+惰性删除是如何工作的呢?

定期删除,redis默认每个100ms检查,是否有过期的key,有过期key则删除。需要说明的是,redis不是每个100ms将所有的key检查一次,而是随机抽取进行检查(如果每隔100ms,全部key进行检查,redis岂不是卡死)。因此,如果只采用定期删除策略,会导致很多key到时间没有删除。

于是,惰性删除派上用场。也就是说在你获取某个key的时候,redis会检查一下,这个key如果设置了过期时间,那么是否过期了?如果过期了此时就会删除。

采用定期删除+惰性删除就没其他问题了么?

不是的,如果定期删除没删除key。然后你也没即时去请求key,也就是说惰性删除也没生效。这样,redis的内存会越来越高。那么就应该采用内存淘汰机制

在redis.conf中有一行配置 maxmemory-policy volatile-lru

该配置就是配内存淘汰策略的(什么,你没配过?好好反省一下自己)

volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰。

volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰。

volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰。

allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰。

allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰。

no-enviction(驱逐):禁止驱逐数据,新写入操作会报错。

ps:如果没有设置 expire 的key,不满足先决条件(prerequisites); 那么 volatile-lru,、volatile-random 和volatile-ttl 策略的行为 和 noeviction(不删除) 基本上一致。


八、Redis 为什么是单线程的


官方FAQ表示,因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了(毕竟采用多线程会有很多麻烦!)Redis利用队列技术将并发访问变为串行访问。

1、绝大部分请求是纯粹的内存操作(非常快速)

2、采用单线程,避免了不必要的上下文切换和竞争条件

3、非阻塞IO优点:

(1)速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)。

(2)支持丰富数据类型,支持string,list,set,sorted set,hash。

(3)支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行。

(4)丰富的特性:可用于缓存,消息,按key设置过期时间,过期后将会自动删除如何解决redis的并发竞争key问题同时有多个子系统去set一个key。这个时候要注意什么呢?不推荐使用redis的事务机制。因为我们的生产环境,基本都是redis集群环境,做了数据分片操作。你一个事务中有涉及到多个key操作的时候,这多个key不一定都存储在同一个redis-server上。因此,redis的事务机制,十分鸡肋。

a、如果对这个key操作,不要求顺序:准备一个分布式锁,大家去抢锁,抢到锁就做set操作即可作了。以此类推。

b、利用队列,将set方法变成串行访问;redis遇到高并发,如果保证读写key的一致性对redis的操作都是具有原子性的,是线程安全的操作,你不用考虑并发问题,redis内部已经帮你处理好并发的问题了


九、Redis 常见性能问题和解决方案?


1、Master 最好不要做任何持久化工作,如 RDB 内存快照和 AOF 日志文件。

2、 如果数据比较重要,某个 Slave 开启 AOF 备份数据,策略设置为每秒同步一次。

3、为了主从复制的速度和连接的稳定性, Master 和 Slave 最好在同一个局域网内。

4、尽量避免在压力很大的主库上增加从库。

5、主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <-Slave3…


十、为什么Redis的操作是原子性的,怎么保证原子性的?


对于Redis而言,命令的原子性指的是:一个操作的不可以再分,操作要么执行,要么不执行。

Redis的操作之所以是原子性的,是因为Redis是单线程的。

Redis本身提供的所有API都是原子操作,Redis中的事务其实是要保证批量操作的原子性。

多个命令在并发中也是原子性的吗?

不一定, 将get和set改成单命令操作,incr 。使用Redis的事务,或者使用Redis+Lua==的方式实现.


最后

腾讯T3大牛总结的500页MySQL实战笔记意外爆火,P8看了直呼内行

腾讯T3大牛总结的500页MySQL实战笔记意外爆火,P8看了直呼内行

对于Redis而言,命令的原子性指的是:一个操作的不可以再分,操作要么执行,要么不执行。

Redis的操作之所以是原子性的,是因为Redis是单线程的。

Redis本身提供的所有API都是原子操作,Redis中的事务其实是要保证批量操作的原子性。

多个命令在并发中也是原子性的吗?

不一定, 将get和set改成单命令操作,incr 。使用Redis的事务,或者使用Redis+Lua==的方式实现.


最后

[外链图片转存中…(img-uzYKyAV9-1719153895371)]

[外链图片转存中…(img-YOqDqEnH-1719153895372)]

<think>嗯,用户想要2025年Redis高频面试题及答案大全。根据引用[2]的内容,里面已经详细列出了Redis面试题的分类和具体问题,正好可以满足用户需求。 用户可能是正在准备技术面试的开发者,需要系统性的Redis复习资料。从引用内容看,这些题目覆盖了Redis核心知识点,包括基础原理、持久化、集群、高可用等,都是面试常考点。 我注意到引用[2]的目录结构很清晰,可以按这个框架组织答案。每个问题都需要给出简洁准确的回答,特别是像"Redis为什么快"、"缓存雪崩解决方案"这类经典问题,必须包含关键技术点。 对于分布式锁这种实践性很强的问题,除了基本原理,还要提醒注意事项,比如超时设置和锁续期,这是实际项目中容易出错的地方。 用户可能还会关注新版本特性,比如Redis 7.0的改进,虽然引用里没提,但可以适当补充。不过要注意控制篇幅,先保证核心问题的完整回答。 最后需要强调答案的权威性,毕竟面试准备不能有技术错误。所有解答都要基于Redis官方文档和主流实践,比如缓存淘汰策略的配置参数要准确。</think>以下是根据2025年Redis高频面试题整理的核心内容及答案解析,涵盖基础原理、集群、高可用、缓存设计等核心领域: --- ### **一、基础原理** 1. **Redis为什么快?** - 纯内存操作 - 单线程避免上下文切换(网络I/O等模块仍多线程) - 非阻塞I/O多路复用(epoll) - 高效数据结构(跳表、哈希表) 2. **Redis支持的数据结构及应用场景** | 数据结构 | 典型场景 | |------------|--------------------------| | String | 缓存、计数器(INCR) | | Hash | 存储对象(用户信息) | | ZSet | 排行榜(分值排序) | | Stream | 消息队列(消费者组) | --- ### **二、持久化与高可用** 3. **RDB vs AOF 区别** ```markdown - RDB:二进制快照,恢复快,可能丢失数据(配置:`save 900 1`) - AOF:日志追加,数据更安全(支持`fsync everysec`) - 可同时开启:重启时优先加载AOF ``` 4. **Redis Sentinel原理** - 监控:Sentinel节点定期检测主节点状态 - 故障转移:主节点失效时,自动选举新主节点 - 通知:向客户端推送新主节点地址 --- ### **三、缓存设计与分布式** 5. **缓存穿透/击穿/雪崩解决方案** | 问题 | 解决方案 | |------------|----------------------------------| | 穿透 | 布隆过滤器 + 空值缓存 | | 击穿 | 互斥锁(SETNX) + 热点数据永不过期 | | 雪崩 | 随机过期时间 + 集群部署 | 6. **分布式锁实现(RedLock算法)** ```python # 伪代码示例 def acquire_lock(servers, key, ttl): lock_value = uuid4() success_count = 0 for server in servers: if server.set(key, lock_value, nx=True, ex=ttl): success_count += 1 return success_count > len(servers)/2 # 过半成功即获锁 ``` **注意点**:时钟漂移问题、锁续期(watchdog机制)[^2] --- ### **四、集群与扩展性** 7. **Redis Cluster分片原理** - 16384个槽(slot)分片,通过`CRC16(key) mod 16384`计算槽位 - 节点间通过Gossip协议通信 - 迁移槽位时支持ASK重定向 8. **集群限制** - 不支持跨节点事务(如MULTI操作多个key) - 批量操作需所有key在同一节点(可用`Hash Tag`强制同槽) --- ### **五、实战优化** 9. **热点缓存预热** - 方案:离线分析日志 + 启动时加载高频数据到Redis - 动态更新:订阅数据库Binlog,实时同步热点数据 10. **内存优化技巧** - 使用`ziplist`编码压缩小数据(配置`hash-max-ziplist-entries 512`) - 启用内存碎片整理(`activedefrag yes`) > ⚠️ **避坑指南**:生产环境慎用`KEYS *`(阻塞线程),改用`SCAN`迭代[^2]。 --- **附:2025高频考点扩展** - Redis 7.0新特性:多线程AOF、Function API - 大Key探测工具:`redis-cli --bigkeys` + 自定义扫描脚本 - 持久化调优:AOF重写时`no-appendfsync-on-rewrite yes` [^1]: 参考《2025年Java高频面试题汇总》分布式系统章节 [^2]: 源自《2025最新Redis面试题大全》集群与高可用解决方案 如果需要完整面试题库(含场景题+代码示例),可点击 [Redis面试宝典] 获取PDF文档。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值