Redis面试题


Redis 是什么?核心优势是什么?

Redis 是基于内存的键值对数据库,支持多种数据结构。
核心优势:

  1. 高性能(纯内存操作,单线程模型);
  2. 高可用(主从、哨兵、集群);
  3. 功能丰富(缓存、分布式锁、消息队列都能做);
  4. 支持持久化,数据不丢

Redis 使用

redis是一个非关系型数据库,项目中主要是用来存储热点数据,减轻数据库压力
​应用场景:缓存、消息队列、实时排行榜、分布式锁、计数器等

Redis 支持哪些数据类型?各自典型场景?

String:缓存、计数器、分布式锁(setnx);
Hash:存储对象(比如用户信息),节省内存;
List:消息队列、最新列表(比如朋友圈动态);
Set:去重、抽奖、交集并集(比如共同好友);
ZSet:排序场景(比如排行榜、延时队列);
补充:还有 Bitmap(布隆过滤器)、Geo(地理位置)等扩展类型。

Redis 为什么这么快?

核心原因:

  1. 纯内存操作,避免磁盘 IO;
  2. 单线程模型,无线程切换、锁竞争开销;
  3. 用 IO 多路复用(epoll)处理网络请求,高效管理连接;
  4. 数据结构优化(比如跳表、压缩列表)。

Redis 持久化有哪两种方式?区别是什么?

RDB:快照持久化,定时把内存数据快照保存到磁盘;优点是恢复快,缺点是可能丢数据;
AOF:日志持久化,记录所有写命令,重启时重放命令恢复;优点是数据更安全,缺点是文件大、恢复慢;
生产常用:RDB+AOF 混合,兼顾性能和数据安全。

Redis 缓存穿透、缓存击穿、缓存雪崩是什么?怎么解决?

缓存穿透:请求不存在的 key,每次都查数据库;解决:布隆过滤器拦截、空值缓存;
缓存击穿:热点 key 过期,大量请求打数据库;解决:热点 key 永不过期、互斥锁;
缓存雪崩:大量 key 同时过期,数据库扛不住;解决:过期时间加随机值、集群部署、限流降级。

Redis 出现内存泄漏怎么排查?

① 用info memory查看内存使用情况;
② 用redis-cli –bigkeys找出大 key;
③ 检查过期键策略,是否有大量过期键没删除;
④ 检查业务代码,是否有大量无用 key 没清理。

Redis 事务如何保证原子性?

Redis 事务不支持回滚,核心是通过一次性执行、命令队列化、错误处理机制实现弱原子性
弱原子性:要么队列中所有命令都执行,要么都不执行;但执行过程中若出现运行时错误(如对字符串做自增),错误命令会失败,其他命令仍会执行,不会回滚。
而 MySQL 是强原子性:一个语句失败,整个事务回滚,所有操作恢复原状。

Redis 是否支持回滚?

​不支持传统回滚:Redis 事务不提供 ROLLBACK,若某条命令失败,后续命令仍会执行。
​替代方案:通过乐观锁(WATCH)或 Lua 脚本实现原子性操作

如何用 Redis 实现分布式锁

  1. Redisson 分布式锁 + Redis 操作(项目主流方案,你高频使用)
    核心原理:用 Redisson 实现 Redis 分布式锁,先加锁再执行所有 Redis 操作,保证同一时间只有一个客户端操作该 key,从根本上避免并发和原子性问题;
    优势:实现简单,高并发下性能稳定,适配你 500+QPS 的库存扣减场景。
  2. 使用 Lua 脚本(Redis 原子性最优方案,企业高级用法)
    核心原理:Redis 会一次性执行整个 Lua 脚本,执行过程中不会被其他命令打断,天然保证原子性;可在脚本中做逻辑判断 + 多命令执行,甚至实现错误回滚(通过代码逻辑);
    优势:原子性最强,减少网络请求(一次脚本执行替代多次 Redis 命令),高并发下性能最优。

Redis 过期键的删除策略?

三种策略:

  1. 惰性删除:访问时才检查是否过期,过期则删除(节省 CPU,可能内存泄漏);
  2. 定期删除:每隔一段时间,随机抽查部分过期键删除(平衡 CPU 和内存);
  3. Redis 用 “惰性删除 + 定期删除” 结合,配合内存淘汰策略兜底。

Redis 管道(pipeline)的作用?原理?

作用:批量发送命令,减少网络往返次数,提升并发;
原理:客户端把多个命令打包发送,Redis 一次性执行,批量返回结果(注意:pipeline 不是原子操作)

如何保证缓存和数据库的数据一致性?

核心原则:最终一致性,常用方案:

  1. 先更数据库,再删缓存(避免并发问题);
  2. 缓存删除失败则重试(比如用 MQ);
  3. 读多写少场景:加延迟双删(删缓存→更数据库→延迟 1s 再删缓存)。

如何优化 Redis 性能?

  1. 用批量操作(pipeline)减少网络请求;
  2. 避免大 key(拆分大 key,比如大 Hash 拆成多个小 Hash);
  3. 合理设置过期时间,避免内存浪费;
  4. 开启持久化优化(比如 AOF 重写、RDB 定时调整);
  5. 集群部署,分摊压力。

数据结构类(高频加分项)

  1. String 底层实现?
    底层是简单动态字符串(SDS),和 Java String 区别:① 可修改;② 预分配空间,减少扩容开销;③ 记录长度,获取长度 O (1)。
    小字符串用 embstr 编码,大字符串用 raw 编码。
  2. Hash 底层实现?
    小哈希:压缩列表(ziplist),节省内存;
    大哈希:哈希表(hashtable),查询更快;
    触发切换的条件:哈希元素数超过阈值,或单个元素值过大。
  3. ZSet 底层实现?
    小 ZSet:压缩列表;
    大 ZSet:跳表(skiplist)+ 哈希表;
    跳表优势:插入、删除、查询都是 O (logN),比红黑树实现简单。

Redis集群

主从复制集群

主节点(master)写数据,从节点(slave)读数据,实现读写分离,提升读的并发能力;
主节点故障后可手动切换到从节点,是哨兵 / 分片集群的基础

  • 核心角色
    主节点(Master):唯一可写节点,处理所有写请求
    从节点(Slave):只读节点,同步主节点数据,处理所有读请求
  • 项目适配场景
    读多写少,可采用主从集群:主节点处理缓存更新(写),从节点处理查询(读),提升读并发能力;
    缺点:主节点故障后需手动切换,无法自动容灾,适合中小规模项目

Redis 主从复制原理?

  1. 从库连接主库,发送 SYNC 命令;
  2. 主库执行 bgsave 生成 RDB 文件,同时记录新的写命令;
  3. 主库把 RDB 文件和新命令发给从库;
  4. 从库加载 RDB,执行新命令,和主库数据同步;
  5. 后续主库有写操作,实时同步给从库(增量复制)。

哨兵模式集群(主从 + 哨兵,自动容灾,企业主流)

在主从复制基础上,增加哨兵节点(Sentinel),实现主节点故障自动切换(无需人工干预),解决主从集群的单点故障问题,是企业中读多写少、数据量适中场景的首选

  • 核心角色
    主 / 从节点:和主从集群一致,负责数据存储和读写分离;
    哨兵节点:监控主从节点状态,主节点故障时自动将最优从节点升级为主节点,并通知其他从节点同步新主节点,同时通知业务系统(如你的 Spring Boot 项目)更新 Redis 地址。
  • 项目适配场景
    哨兵模式:既实现读写分离提升性能,又能自动容灾,主节点故障后秒级切换,保证库存服务不中断;
    缺点:所有节点存储全量数据,无法解决海量数据存储问题(如单节点内存不足)。
  • 项目对接技巧(你的 Spring Boot 项目如何连接哨兵集群)
    无需配置具体 Redis 主从地址,直接配置哨兵地址,Spring Boot 会自动从哨兵获取主节点地址,故障切换后自动更新:

Redis 哨兵(Sentinel)的作用?核心流程?

哨兵是监控 Redis 集群的工具,核心作用:

  1. 监控主从节点是否存活;
  2. 主库故障时自动切换(选新主库);
  3. 通知客户端主库地址变更。
    核心流程:主库宕机→哨兵集群投票→选一个从库升主→其他从库同步新主→通知客户端。

分片集群(Redis Cluster,海量数据 + 高并发,大型微服务项目)

哨兵模式的全量数据存储问题,将海量数据分片存储到不同主节点,每个主节点只存储部分数据,同时搭配从节点实现高可用,支持水平扩容(新增节点即可扩容),适合数据量巨大、读写并发极高的微服务项目

  • 核心特性
    分片规则:采用哈希槽(Hash Slot) 机制,Redis 集群共有16384 个哈希槽,每个主节点分配部分槽位,数据根据key的哈希值映射到对应槽位的节点;
    节点角色:至少3 主 3 从(6 节点),每个主节点对应 1 个从节点,主节点负责写 + 槽位管理,从节点负责读 + 容灾;
    自动容灾:主节点故障时,其从节点自动升级为主节点,接管槽位;
    无中心节点:所有节点平等,可互相通信,客户端连接任意节点即可访问全集群数据

Redis 分片集群(Cluster)原理?如何分片?

  1. 采用哈希槽(16384 个)分片,槽位 = CRC16(key) % 16384;
  2. 每个节点负责一部分槽位,数据按槽位分布;
  3. 主从复制:每个主节点有从节点,故障时从节点升主;
  4. 客户端请求时,先定位槽位对应的节点,再发请求。

Redis 三种集群的区别及适用场景

开发中常用 Redis 主从、哨兵、分片三种集群:

  1. 主从集群是基础,实现读写分离,提升读并发,但主节点故障需手动切换,适合中小规模读多写少场景;
  2. 哨兵模式基于主从,增加哨兵实现主节点故障自动切换,解决单点故障,是企业主流,保证核心业务高可用;
  3. 分片集群采用哈希槽机制,将数据分片存储,支持海量数据和水平扩容,解决单节点内存瓶颈,缺点是不支持跨槽位多 key 操作。

Redis 集群扩容怎么做?

① 新增节点,加入集群;
② 迁移哈希槽(把旧节点的槽位迁移到新节点);
③ 迁移过程中,Redis 会自动处理请求,不影响业务(无缝扩容)。

Redis集群实战避坑(你项目中踩过的坑 / 注意事项)

生产环境必开持久化:开启 AOF+RDB 混合持久化,防止集群故障导致数据丢失;
节点密码统一:所有主从 / 哨兵 / 分片节点密码必须一致,否则同步 / 监控失败;
禁止单服务器模拟集群:生产环境必须用独立服务器,单服务器多端口模拟会因服务器故障导致整个集群瘫痪;
分片集群 key 设计:若需多 key 操作,用哈希标签(如{user}_1、{user}_2)让多个 key 映射到同一槽位;
监控与扩容:生产环境用 Redis-Exporter+Prometheus 监控集群状态,分片集群通过redis-cli –cluster add-node实现无缝扩容。
基础配置:关闭防火墙 / 开放 Redis 端口(6379 / 哨兵 26379)、禁用透明大页、配置内核参数;所有节点密码统一,开启AOF+RDB 混合持久化(防止数据丢失,贴合你库存 / 课程数据核心场景)。

Redis集群如何搭建

服务器环境:CentOS7/8 Linux 服务器,哨兵模式至少 2 台(1 主 1 从 + 哨兵),分片集群建议 6 台(3 主 3 从,企业标配);Redis 版本选 5.0+(你项目中主流稳定版)。
基础配置:关闭防火墙 / 开放 Redis 端口(6379 / 哨兵 26379)、禁用透明大页、配置内核参数;所有节点密码统一,开启AOF+RDB 混合持久化(防止数据丢失,贴合你库存 / 课程数据核心场景)。
项目适配:哨兵模式用于航天云膜库存扣减、分布式锁、双缓存比对等核心高可用场景;分片集群用于青松职考 10 万 + 课程数据索引、元数据集成平台日均 10 万 + 数据存储等海量数据场景。


文章作者: zrh
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 zrh !
  目录