Redis深入面试题

29 阅读4分钟

一、源码与架构原理

  1. Redis是单线程吗?具体是如何实现的?

    • Redis主线程处理命令,采用I/O多路复用(epoll/kqueue/select)异步监听客户端请求,避免了多线程上下文切换开销。
  2. Redis的数据结构底层实现?

    • 字符串(String)底层是简单动态字符串(SDS),支持自动扩容,避免了传统C字符串的缺点。
    • Hash内部采用两种编码:ziplist(压缩列表)和hashtable,自动根据大小切换。
    • List底层是quicklist,结合双向链表和ziplist,兼顾内存和性能。
    • Set用哈希表或整数集合(intset)实现。
    • ZSet(有序集合)用跳表(skiplist)和哈希表结合实现。
  3. 什么是Redis的慢查询日志?如何定位性能瓶颈?

    • Redis会记录执行时间超过阈值的命令。分析慢查询日志结合命令统计,可以发现热点命令和性能瓶颈。
  4. Redis是如何保证数据的原子性的?

    • 单线程顺序执行命令,命令执行过程中不会被打断,保证原子性。Lua脚本也保证单条脚本内所有操作原子执行。
  5. Redis的RDB持久化是如何实现的?

    • 使用fork子进程创建快照,子进程负责写入RDB文件,主进程继续处理请求,避免阻塞。
  6. AOF持久化的工作机制及重写机制?

    • 追加写日志记录每个写操作,重写时生成新的最小化AOF文件,防止文件膨胀。

二、集群与高可用

  1. Redis集群的分片原理是怎样的?

    • 使用16384个槽(slot)分配给各个节点,键通过CRC16(key) % 16384计算槽位,槽分配到不同节点,实现数据分片。
  2. Redis集群中槽迁移的流程?

    • 新节点加入后,部分槽从旧节点迁移到新节点,迁移过程中会转发请求保证一致性。
  3. Redis哨兵(Sentinel)的工作流程?

    • 监控主从节点状态,判断主节点宕机后,选举新主节点,通知客户端重新连接。
  4. 什么是Redlock算法?它解决了什么问题?

    • 分布式锁算法,通过多个Redis实例获取锁,防止单点故障导致锁失效。
  5. Redis集群如何保证强一致性?

    • Redis默认是最终一致性,集群中采用异步复制,可能存在数据丢失,强一致性需要业务层做保障。

三、性能优化与调优

  1. Redis内存优化有哪些技巧?

    • 使用哈希小对象编码(hash-max-ziplist-entries和hash-max-ziplist-value)
    • 减少key和value的冗余长度
    • 合理使用压缩列表和快速列表
    • 设置合理过期策略,避免大key
  2. Redis大key问题怎么处理?

    • 避免存储过大的字符串、列表、集合等
    • 使用分片拆分大数据
    • 监控大key,定期清理或拆分
  3. 如何避免缓存穿透、缓存击穿和缓存雪崩?

    • 缓存穿透:使用布隆过滤器或空值缓存
    • 缓存击穿:加互斥锁,或者用永不过期的热点缓存
    • 缓存雪崩:设置过期时间随机,分散缓存失效时间
  4. Redis为什么会阻塞?如何避免?

    • 大key操作(如keys、flushall)
    • 持久化fork过程CPU或内存压力
    • 使用scan替代keys,合理配置持久化,避免大key
  5. Redis的慢日志怎么调优?

    • 调整慢查询阈值,定位高耗时命令,优化数据结构和访问方式

四、实战题

  1. 设计一个基于Redis的限流方案。

    • 使用计数器和过期时间实现固定窗口限流
    • 使用滑动窗口或令牌桶算法实现更精准限流(Lua脚本)
  2. 如何用Redis实现分布式队列?

    • 使用List结构的lpush/rpop
    • 结合阻塞命令(BLPOP)实现消息队列功能
  3. 你遇到过Redis宕机怎么办?如何恢复数据?

    • 查看AOF和RDB文件恢复数据
    • 使用哨兵自动切换主节点
    • 评估数据丢失风险,做好备份
  4. Redis在高并发场景中怎么保证写操作性能?

    • 使用pipeline减少网络往返
    • 适当使用Lua脚本批量处理
    • 减少大key操作,避免阻塞