redis常见面试题

1. Redis 是做什么的?即在哪些场景下使用?

核心概念: Redis 是一个基于内存的、键值对存储的 NoSQL 数据库,以其极高的性能丰富的数据结构强大的功能而闻名。

主要应用场景:

  • 缓存:这是最核心、最广泛的使用场景。将热点数据存放在 Redis 中,减少对后端数据库(如 MySQL)的直接访问,极大提升应用响应速度和承载能力。
  • 会话存储:将 Web 应用的分布式会话(Session)集中存储在 Redis 中,解决了单服务器会话无法共享的问题,是实现应用水平扩展的常用手段。
  • 消息队列:利用 Redis 的 List(阻塞操作)、Pub/Sub(发布/订阅)或 Stream(5.0版本后,最专业)数据结构,实现简单的异步任务队列、消息广播等。
  • 排行榜/计数器:利用 ZSet(有序集合)可以轻松实现实时排行榜。利用 String 类型的 INCR/DECR 命令实现高并发下的计数器(如微博阅读量、点赞数)。
  • 实时系统:如实时监控、实时数据分析、实时反作弊系统,利用 Redis 的高吞吐和低延迟特性进行实时数据处理。
  • 社交关系:利用 Set(集合)的交并差操作,可以方便地实现共同关注、共同好友等功能。
  • 分布式锁:利用 SET key value NX PX timeout 命令可以实现一个简单的分布式锁,用于控制分布式系统对共享资源的并发访问。

2. 如果监控 Redis 是否出现故障?

一个全面的 Redis 监控体系应包括:

  1. 基础资源监控
    • CPU 使用率:持续过高可能表示存在复杂查询或 RDB/AOF 持久化。
    • 内存使用率:监控 used_memory 和 maxmemory,防止内存耗尽触发 OOM 或逐出策略。
    • 网络带宽:监控输入/输出流量,判断是否存在瓶颈。
    • 磁盘 I/O:特别是开启 AOF 时,磁盘性能会影响 Redis 的写入性能。
  2. Redis 关键指标监控
    • 连接数 (connected_clients):连接数突增可能意味着客户端连接泄漏。
    • 阻塞客户端数 (blocked_clients):数量大于 0 表示有客户端因 BLPOP 等命令被阻塞,需检查。
    • Key 空间信息 (keyspace_hitskeyspace_misses):命中率低可能表示缓存失效或设计不合理。
    • 持久化状态
      • rdb_last_bgsave_status / aof_last_bgrewrite_status:检查上次 RDB/AOF 重写是否成功。
      • aof_last_write_status:检查上次 AOF 写入是否成功。
    • 复制状态 (master_link_statusslave_repl_offset):在主从架构中,监控主从连接状态和复制延迟。
    • Keyspace 命中率keyspace_hits / (keyspace_hits + keyspace_misses),命中率过低需要考虑缓存有效性。
  3. 服务可用性监控
    • 定期 PING:通过向 Redis 实例发送 PING 命令,检查其是否响应 PONG,这是最基本的存活检查。
    • 慢查询监控:通过 slowlog get 命令获取慢查询日志,分析性能瓶颈。

3. Redis客户端timeout报错突然增加,排查思路是怎样的?

这是一个典型的性能问题,排查思路应由浅入深:

  1. 检查 Redis 服务端状态
    • 资源瓶颈:使用 info 命令查看 CPU、内存使用率是否达到瓶颈。
    • 慢查询:使用 slowlog get 检查是否有大 Key 或复杂命令阻塞了服务端,导致后续命令排队超时。
    • 持久化影响:检查是否正在执行 BGSAVE 或 BGREWRITEAOF,这两个操作会 fork 子进程,可能导致主进程短暂阻塞(尤其内存越大,fork 耗时越长)。
  2. 检查网络
    • 网络延迟/丢包:使用 ping/traceroute 检查客户端与 Redis 服务器之间的网络状况。
    • 连接数:检查 connected_clients 是否达到 maxclients 上限,导致新连接被拒绝。
  3. 检查客户端
    • 客户端资源:检查客户端应用服务器本身的 CPU、内存、网络是否正常。
    • 连接池:检查客户端连接池配置是否合理(如最大连接数过小),或者是否存在连接泄漏(获取连接后未释放)。
    • 业务逻辑:检查是否有突发的高并发请求,或者是否执行了 KEYS * 等危险命令。

4. 请简单描述pipeline功能,为什么pipeline功能会提升redis性能?

  • 是什么:Pipeline 是一种客户端技术。它将多个 Redis 命令打包,一次性发送给服务器,然后再将服务器返回的所有响应一次性读取回来。
  • 为什么能提升性能
    • 减少网络往返时间:在不使用 Pipeline 时,每条命令都需要经历“发送->等待->接收”的循环,RTT 占了大部分时间。Pipeline 将 N 条命令的 N 次 RTT 缩减为 1 次。
    • 降低系统调用开销:减少了 read() 和 write() 系统调用的次数。

注意:Pipeline 中的命令在服务器端仍然是串行执行的,并非原子操作。如果需要原子性,应使用事务(MULTI/EXEC)。


5. 本地redis-client访问远程Redis服务出错,说出几种常见的错误?

  1. 连接被拒绝 Connection refused:远程 Redis 服务未启动,或防火墙/安全组阻止了访问。
  2. 认证失败 NOAUTH Authentication required:配置了密码,但客户端未提供或提供了错误的密码。
  3. 超过最大连接数 ERR max number of clients reached:Redis 服务器的客户端连接数已达到 maxclients 配置的上限。
  4. 命令不存在 ERR unknown command:客户端发送的命令在该 Redis 版本中不支持。
  5. 内存不足 OOM command not allowed when used memory > 'maxmemory':Redis 内存已满,且配置的逐出策略无法释放更多内存。
  6. 网络超时 Read timed out / Connection timed out:网络延迟高或丢包严重,或服务端因持久化等原因阻塞。

6. key-value的大小超大或单key的qps超高,会对Redis本身造成什么样的影响、会对访问Redis的其他客户端造成什么样的影响?

  • 大 Key 的影响
    • 对 Redis 本身
      • 内存不均:可能导致集群中某个节点内存使用率远高于其他节点。
      • 持久化阻塞:在 bgsave fork 子进程时,操作大 Key 会导致内存拷贝耗时剧增,主进程阻塞。
      • 网络拥堵:获取或删除一个大 Key 会占用大量带宽。
    • 对其他客户端
      • 因为上述操作(特别是持久化 fork 和网络传输)会消耗大量资源和时间,导致其他客户端的请求被延迟处理,出现超时。
  • 热 Key 的影响
    • 对 Redis 本身
      • CPU 压力:所有请求集中到一个节点的一个分片,导致该节点 CPU 负载极高。
      • 物理网卡瓶颈:流量打满单个机器网卡。
    • 对其他客户端
      • 因为热 Key 所在的 Redis 节点/线程资源被耗尽,部署在该节点上的其他 Key 的访问也会受到严重影响,响应变慢。

7. Zabbix 监控 Redis 哪些监控项?

Zabbix 通过自定义模板或脚本采集 Redis 的指标,主要包括:

  • 性能指标instantaneous_ops_per_sec(每秒操作数),hit rate(命中率)。
  • 内存指标used_memoryused_memory_rssmem_fragmentation_ratio(内存碎片率)。
  • 连接指标connected_clientsrejected_connections(拒绝的连接数)。
  • 持久化指标rdb_last_bgsave_statusaof_last_bgrewrite_statusaof_current_size
  • 复制指标(主从):master_link_statusslave_lag(复制延迟)。
  • Keyspace 指标keyspace_hitskeyspace_missesexpired_keys

8. RDB和AOF持久化区别

特性RDBAOF
持久化方式生成某个时间点的数据快照记录所有写命令,以日志形式追加
数据完整性可能丢失最后一次快照后的数据根据 fsync 策略(每秒/每次/无),数据丢失更少
文件大小小(二进制压缩)大(日志文本,但可重写优化)
恢复速度(直接加载数据到内存)(需要逐条执行命令)
对性能影响bgsave 时 fork 子进程,内存开销大,可能阻塞主要取决于 fsync 策略,everysec 是性能和安全性的折中
优先级如果同时开启,Redis 重启时 AOF 优先,因为数据更完整

生产环境建议:通常两者都开启,用 AOF 保证数据安全,用 RDB 做冷备份和快速恢复。


9. docker拉取一个Redis如何实现数据持久化保存?

Docker 容器本身是易失的,必须将 Redis 的数据目录映射到宿主机。

bash复制下载

# 方法一:使用 Volume(推荐,由Docker管理)
docker run -d --name my-redis -v redis_data:/data redis

# 方法二:使用 Bind Mount(直接映射到宿主机目录)
docker run -d --name my-redis -v /host/path/to/data:/data redis

# 同时,可以自定义配置文件,确保 RDB 或 AOF 被启用并指向 /data 目录
docker run -d --name my-redis -v /host/path/redis.conf:/etc/redis/redis.conf -v redis_data:/data redis redis-server /etc/redis/redis.conf

关键是将容器内的 /data(默认持久化文件存储路径)持久化到宿主机。


10. Redis 支持哪些数据类型

  1. String:字符串,可以是文本、数字或二进制数据。
  2. List:字符串列表,按插入顺序排序,支持两端插入/弹出。
  3. Set:无序、唯一的字符串集合。
  4. Hash:键值对集合,适合存储对象。
  5. ZSet:有序集合,每个成员关联一个分数,按分数排序。
  6. Bitmaps:位图,本质是 String,可进行位操作。
  7. HyperLogLog:用于基数统计(估算唯一元素数量)。
  8. Stream:用于实现消息队列,支持多消费者组。

11. Redis 如何实现消息队列

  1. List + BLPOP/BRPOP
    • 生产者用 LPUSH 将任务放入列表。
    • 消费者用 BRPOP 阻塞地等待并获取任务。支持多个消费者。
    • 缺点:消息只能被一个消费者消费,无法广播。
  2. Pub/Sub
    • 生产者向频道发布消息,所有订阅了该频道的消费者都会收到。
    • 缺点:消息是非持久化的,消费者离线期间的消息会丢失。
  3. Stream推荐,5.0版本后):
    • 类似 Kafka,消息是持久化的。
    • 支持消费者组,同一个组内的消费者竞争消费,实现负载均衡。
    • 支持消息确认机制,确保消息至少被处理一次。

12. 常见的redis集群架构有哪些,他们之间的优缺点对比

架构优点缺点适用场景
主从复制1. 数据备份
2. 读写分离,扩展读能力
1. 主节点故障需手动切换
2. 写能力/容量无法扩展
读多写少,容灾备份
哨兵模式1. 主从自动故障转移,高可用
2. 部署简单
1. 写能力/容量无法扩展
2. 存储容量受单机限制
对高可用有要求,但数据量不大
官方集群1. 数据分片,扩展写能力和容量
2. 高可用,内置主从和故障转移
1. 架构复杂,部署维护稍麻烦
2. 客户端需要支持集群协议
3. 不支持跨节点事务
大数据量、高并发、高可用的标准生产方案

13. 主从复制工作原理

  1. 同步
    • 从节点启动后,向主节点发送 PSYNC 命令。
    • 主节点执行 BGSAVE 生成 RDB 快照,并将其发送给从节点。从节点清空旧数据,加载 RDB。
    • 在主节点生成和发送 RDB 期间的新写命令,会缓存在内存的 复制缓冲区 中。
  2. 命令传播
    • RDB 加载完成后,主节点将复制缓冲区中积压的命令发送给从节点执行。
    • 之后,主节点每收到一个写命令,就异步地发送给所有从节点,保持数据最终一致。

14. Redis 如何实现高可用

核心是 自动故障转移,主要依靠两种架构:

  1. Redis Sentinel
    • 哨兵是一个独立的进程,监控主从节点的健康状态。
    • 当主节点被判定为故障时,哨兵集群会自动协商,将一个从节点提升为新的主节点,并让其他从节点和客户端指向新的主节点。
  2. Redis Cluster
    • 集群模式本身内置了高可用能力。每个数据分片都是一个主从单元。
    • 当某个主节点故障时,其下属的从节点会被集群自动提升为主节点,继续提供服务。

15. 哨兵工作原理

  1. 监控:每个哨兵每秒向所有主、从节点和其他哨兵发送 PING 命令,以检测它们是否“主观下线”。
  2. 判定主观下线:如果一个节点在配置时间内未有效回复 PING,哨兵会将其标记为“主观下线”。
  3. 判定客观下线:当一个哨兵认为主节点主观下线后,它会询问其他哨兵是否也认为该主节点下线。当达到法定数量(通常为哨兵数/2 + 1)时,该主节点被标记为“客观下线”。
  4. 选举领导者哨兵:需要故障转移时,哨兵们会通过 Raft 算法选举出一个领导者哨兵来执行故障转移操作。
  5. 故障转移:领导者哨兵在已下线的原主节点的从节点中,选择一个最优的(如复制偏移量最新)将其提升为新的主节点,并让其他从节点复制新的主节点,最后通知客户端配置更新。

16. Redis 集群的工作原理

  • 数据分片:采用之前介绍的 槽位 机制。将 16384 个槽位分配给集群中的所有主节点。
  • 去中心化:客户端可以直接连接到任意节点。如果该节点没有所需数据,会返回 MOVED 重定向错误,指引客户端连接到正确的节点。
  • 高可用:每个主节点都有 N 个(N>=1)从节点。主节点故障时,其从节点会接管它负责的槽位,成为新的主节点。

17. Redis 集群如何避免脑裂?

脑裂指一个集群中出现了多个主节点。Redis 主要通过以下配置来降低脑裂风险:

  1. min-replicas-to-write:主节点必须至少有 N 个从节点连接,才允许接受写请求。这确保了在主节点与大多数从节点失联时,它会停止写入,防止旧主节点在分区中接收脏数据。
  2. min-replicas-max-lag:从节点的复制延迟必须小于 N 秒,才被计入 min-replicas-to-write

通过这两个配置,可以保证在主节点网络分区时,如果它无法连接到足够多且健康的从节点,它会自我降级,停止写入,从而避免出现“双主”和数据冲突。


18. Redis 集群最少几个节点?为什么?

  • 最少 3 个主节点
  • 为什么:这是由集群的故障检测主节点选举机制决定的。集群节点间使用 Gossip 协议通信,需要超过半数的节点认为某个主节点下线,才能将其判定为真正故障并触发故障转移。2 个节点时,如果 1 个节点故障,剩下的 1 个节点无法形成多数派(1 < 2/2+1? 1<1.5? 不成立),无法做出决策。3 个节点时,即使 1 个节点故障,剩下的 2 个节点也能形成多数派(2 > 1.5),可以完成故障转移。

19. Redis 的集群槽位多少个?

16384 个(2^14)。


20. Redis集群中某个节点缺少一个槽位是否能使用?

不能。 在 Redis 集群的正常模式下,所有 16384 个槽位都必须被分配给集群中的主节点,集群才会提供完整的服务。如果有任何一个槽位未被分配(比如负责它的节点宕机了,且没有可用的从节点接替),那么集群会进入 FAIL 状态,并停止服务


21. Redis数据写入的时候是怎么在各个节点槽位分配数据的?

  1. 客户端对某个 Key 执行写操作。
  2. 客户端本地计算该 Key 的槽位号:CRC16(key) % 16384
  3. 客户端根据本地缓存的“槽位-节点”映射表,直接连接负责该槽位的节点进行写入。
  4. 如果客户端连错了节点,该节点会返回 MOVED <slot> <correct-node-ip:port> 错误,引导客户端连接到正确的节点。

22. Redis的数据存储是以什么样的方式存储?

在内存中,Redis 使用自定义的哈希表跳跃表压缩列表等高效数据结构来存储不同类型的键值,这也是其性能极高的原因之一。


23. Redis集群的各槽位和总槽位之间什么关系?

部分与整体的关系。

  • 总槽位:一个固定的、完整的集合,大小为 16384。它代表了整个集群的数据空间。
  • 各槽位:总槽位被划分给集群中的各个主节点。每个主节点负责总槽位的一个子集。所有主节点负责的槽位子集之和,必须等于总槽位。

24. Redis集群中有一个节点内存使用明显偏大,可能是原因是什么?

  1. 数据倾斜:该节点分配的槽位中包含了大 Key,或者包含了热 Key 导致数据量本身比其他节点多。
  2. Hash Tag 使用不当:使用 {} 将不同的 Key 强制路由到同一个槽位,如果这个策略设计不当,会导致大量数据集中到同一个节点。
  3. 该节点为主节点,且从节点复制延迟大:如果从节点长时间断开连接或复制延迟很大,主节点的复制积压缓冲区会占用较多内存。

25. Redis部署有几种模式

  1. 单机模式:单个 Redis 实例,简单易用,无高可用和扩展性。
  2. 主从复制模式:一主多从,实现数据备份和读写分离。
  3. 哨兵模式:在主从基础上增加了哨兵进程,实现自动故障转移,达到高可用。
  4. 集群模式:多主多从,实现数据分片、高可用和高并发,是应对大数据量和高流量的终极方案。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注