Spring集成Redis面试题库
生成时间: 2026-05-21 23:43 题目数量: 10题
本轮 Spring集成Redis面试题库(带答案)
【面试题】1. Redis的ZSet数据结构底层是如何实现的?为什么使用跳表而不是红黑树?
【标准答案】 ZSet底层有两种编码方式:元素少于128个且每个元素小于64字节时用ziplist(紧凑),否则用skiplist + hashtable组合。跳表相比红黑树有几个优势:第一,实现简单,Redis作者认为跳表代码可维护性更高;第二,跳表范围查询效率更高,ZSet的核心场景就是范围操作(ZRANGE、ZRANGEBYSCORE),跳表只需找到起点然后顺序遍历,时间复杂度O(logN + M),M是结果集大小;第三,跳表的内存占用更友好,平均每个节点只需要1.33个指针,而红黑树固定2个。Redis用的是带有层级概率为1/4的跳表,查询时间复杂度O(logN),插入删除也是O(logN),完全满足需求。
【面试题】2. Spring Data Redis中RedisTemplate和StringRedisTemplate有什么区别?什么场景用哪个?
【标准答案】 核心区别在序列化策略。StringRedisTemplate继承自RedisTemplate<String, String>,Key和Value都使用StringRedisSerializer,存进去是什么样,取出来就是什么样,比如存"hello"就是"hello"。RedisTemplate默认用的是JdkSerializationRedisSerializer,存"hello"会变成一串二进制数据,包含Java类元信息,用redis-cli查看是乱码。实际项目中我推荐用StringRedisTemplate或自定义RedisTemplate配置GenericJackson2JsonRedisSerializer,因为跨语言兼容性好,调试方便。只有在需要存储复杂Java对象且不关心跨语言访问时才用默认JDK序列化。我会在配置类里自定义RedisTemplate<String, Object>,Key用String序列化,Value用JSON序列化。
【面试题】3. 什么是Redis的缓存雪崩?线上如何预防和解决?
【标准答案】 缓存雪崩就是大量缓存Key同时失效,请求全部打到数据库,导致数据库压力骤增甚至宕机。常见场景是批量设置了相同过期时间。预防方案有几个:第一,设置随机过期时间,比如基础TTL加上随机值(1-5分钟),避免同时失效;第二,设置热点数据永不过期,配合主动更新策略;第三,使用多级缓存,本地缓存(Caffeine)+ Redis + 数据库,本地缓存设置更短TTL做兜底;第四,开启Redis持久化并做好高可用部署。发生时的应急方案:第一,快速熔断降级,用Hystrix或Sentinel限流;第二,预热缓存,异步加载数据到Redis;第三,临时开启数据库只读或限流保护。我的经验是预防大于治理,上线前检查批量缓存是否设置随机TTL。
【面试题】4. Redis的RDB和AOF持久化有什么区别?生产环境怎么选择?
【标准答案】 RDB是快照,保存某个时间点的全量数据,生成二进制文件,恢复快但可能丢失最后一次快照后的数据。AOF是追加写日志,记录每个写命令,数据安全性高但文件大、恢复慢。RDB适合对数据丢失不敏感、追求高性能恢复的场景;AOF适合数据安全性要求高的场景。生产环境我推荐混合持久化,Redis 4.0+支持:RDB做基础快照,AOF记录增量操作,既保证恢复速度又减少数据丢失。配置上AOF的fsync策略用everysec,每秒刷盘,最多丢1秒数据。还要注意AOF重写机制,文件大小超过阈值自动重写压缩。我的实践经验是开启混合持久化,RDB每小时全量快照,AOF每秒刷盘,配合主从架构保证高可用。
【面试题】5. 如何用Redis实现分布式锁?SET NX EX有什么问题?Redisson如何解决?
【标准答案】 最简单的分布式锁用SET key value NX EX seconds,NX保证互斥,EX设置过期防止死锁。但这个方案有几个问题:第一,锁超时问题,业务执行时间超过过期时间,锁自动释放,其他线程获得锁导致并发问题;第二,误删问题,线程A的锁过期释放后,线程B获得锁,A执行完删除了B的锁;第三,不可重入,同一线程多次获取同一把锁会失败。Redisson解决了这些问题:第一,看门狗机制,默认锁30秒过期,后台线程每10秒续期,业务没执行完就一直续期;第二,用Lua脚本保证原子性,删除锁时先判断value是否匹配,匹配才删除;第三,Hash结构存储线程ID和重入次数,实现可重入。生产环境我推荐用Redisson的RLock,还支持公平锁、读写锁、联锁,配合wait tryLock设置等待时间。
【面试题】6. Spring Cache注解@Cacheable的缓存Key是如何生成的?如何自定义?
【标准答案】 @Cacheable默认的Key生成策略是SimpleKeyGenerator:如果没有参数,返回SimpleKey.EMPTY;有一个参数,直接返回该参数;多个参数,返回包含所有参数的SimpleKey对象。问题在于参数是对象时,默认equals和hashCode可能不符合预期,导致缓存失效或命中错误。自定义Key有两种方式:第一,用SpEL表达式指定key属性,比如@Cacheable(value="user", key="#id"),支持#result、#root.target等变量;第二,实现KeyGenerator接口,重写generate方法,注入到Spring容器。实际项目中我会用SpEL表达式,简单灵活。复杂场景自定义KeyGenerator,比如用@Cacheable(key="#user.id + '_' + #type")拼接业务主键。还要注意Key的长度控制,太长影响性能。
【面试题】7. Redis Cluster的16384个槽位是如何分配的?节点故障如何转移?
【标准答案】 Redis Cluster把数据空间划分为16384个槽位(slot),每个Key通过CRC16(key) % 16384计算归属槽位,槽位分配给集群节点,每个节点负责一部分槽位。为什么是16384而不是更多?因为节点之间Gossip通信要交换槽位信息,16384个槽位用2KB的位图就能表示,网络传输开销小。节点故障转移机制:第一,每个节点监控其他节点,主观下线(PFAIL)检测;第二,当半数以上主节点认为某节点下线,标记为客观下线(FAIL);第三,该节点的从节点发起选举,获得多数主节点投票后升级为主节点;第四,新主节点接管槽位,继续提供服务。我的经验是生产环境至少3主3从,每个主节点至少1个从节点做故障转移,用redis-cli cluster meet搭建集群。
【面试题】8. 如何用Redis实现接口限流?滑动窗口和令牌桶算法有什么区别?
【标准答案】 常见限流算法有四种:固定窗口、滑动窗口、令牌桶、漏桶。固定窗口用INCR计数,简单但有临界突变问题;滑动窗口用ZSet记录请求时间戳,精确但内存消耗大。令牌桶是按固定速率放令牌,请求获取令牌,获取不到则拒绝,支持突发流量;漏桶是请求先进入队列,按固定速率处理,严格控制速率。我用Redis实现滑动窗口限流:用ZSet存储请求时间戳,ZREMRANGEBYSCORE删除窗口外的请求,ZCARD统计窗口内请求数。用Lua脚本保证原子性,避免并发问题。令牌桶实现:用一个Key存储令牌数,定时任务补充令牌,请求时DECR扣减,负数则拒绝。实际项目中我用Redisson的RRateLimiter,基于令牌桶实现,支持分布式限流。配置上结合业务场景:API限流用令牌桶(允许突发),秒杀场景用漏桶(严格控制)。
【面试题】9. Redis的HyperLogLog和Bitmap有什么区别?在线人数统计用哪个?
【标准答案】 HyperLogLog是基数估算算法,用于统计不重复元素数量,标准误差0.81%,内存占用固定12KB,适合海量数据去重统计,但不存储原始数据。Bitmap是位图,每个元素用1个bit表示存在与否,支持位运算(AND/OR/XOR),精确统计但内存占用与最大ID相关。在线人数统计场景:如果用户ID连续且范围可控(比如用户ID 1-1000万),用Bitmap,SETBIT设置在线状态,BITCOUNT统计在线人数,精确且支持位运算;如果用户ID不连续或数量巨大,用HyperLogLog,PFADD添加用户ID,PFCOUNT估算在线人数,节省内存但不精确。我的经验是社交应用用HyperLogLog统计UV,游戏服务用Bitmap统计在线玩家(支持位运算找共同在线好友)。还有一种方案用Set存储在线用户ID,精确但内存消耗大,适合小规模场景。
【面试题】10. 如何排查Redis慢查询?线上Redis响应慢怎么办?
【标准答案】 排查Redis慢查询分三步:第一,开启慢查询日志,设置slowlog-log-slower-than(默认10000微秒),用SLOWLOG GET查看慢命令;第二,用INFO命令查看监控指标,关注used_memory(内存使用)、instantaneous_ops_per_sec(QPS)、connected_clients(连接数)、blocked_clients(阻塞客户端);第三,用LATENCY监控延迟,LATENCY LATEST查看最近延迟事件。响应慢的常见原因和解决方案:第一,执行了慢命令(KEYS *、大集合操作),改用SCAN、拆分大Key;第二,内存不足触发淘汰策略,检查maxmemory配置和淘汰策略;第三,网络延迟或带宽不足,用INFO replication查看同步延迟;第四,AOF重写或RDB快照导致阻塞,调整持久化策略或使用子进程重写;第五,连接池耗尽,检查连接池配置(Lettuce默认并发8)。我的经验是上线前压测,开启慢查询监控,配置告警,定期审查BigKey和HotKey。
生成完成时间: 2026-05-21 23:43