Redis面试核心知识点
Redis 的五种数据结构各有特色,用对了才能发挥它的优势。很多人只用到了 String 和 Hash,却不知道 List、Set、ZSet 在特定场景下更合适。本文从应用场景出发,讲什么时候用什么类型。
一、数据类型与应用
#
1.1 五种基本类型
| 类型 | 底层结构 | 典型场景 |
|---|---|---|
| String | SDS | 缓存、计数器、分布式锁 |
| Hash | Ziplist/Hashtable | 对象存储、购物车 |
| List | Quicklist | 消息队列、时间线 |
| Set | Intset/Hashtable | 标签、共同关注、抽奖 |
| ZSet | SkipList+Hash | 排行榜、延迟队列 |
#
1.2 特殊类型
- Bitmap: 位图统计,如用户签到
- HyperLogLog: 基数统计,UV计算
- GEO: 地理位置,附近的人
- Stream: 消息队列,类似Kafka
#
1.3 高频面试题
Q: Redis为什么快?
- 纯内存操作
- 单线程避免上下文切换
- IO多路复用(6.0后多线程IO)
- 高效的数据结构
Q: String的SDS相比C字符串的优势?
- O(1)获取长度
- 二进制安全
- 预分配减少内存重分配
二、持久化机制
#
2.1 RDB vs AOF
| 特性 | RDB | AOF |
|---|---|---|
| 文件体积 | 紧凑、小 | 较大 |
| 恢复速度 | 快 | 慢 |
| 数据安全 | 可能丢数据 | 更持久 |
| 性能影响 | fork时阻塞 | 持续写入 |
#
2.2 混合持久化(Redis 4.0+)
- RDB做全量,AOF做增量
- 重写时先RDB格式再AOF格式
#
2.3 高频面试题
Q: AOF重写的原理?
BGREWRITEAOF子进程进行- 写时复制(COW)机制
- 重写期间新命令写入AOF缓冲区
三、高可用架构
#
3.1 主从复制
- 全量同步:RDB文件 + 缓冲区命令
- 增量同步:复制偏移量 + 复制积压缓冲区
- 无磁盘复制(diskless replication)
#
3.2 哨兵Sentinel
- 监控、通知、自动故障转移
- 至少需要3个哨兵节点
- 主观下线(SDOWN) -> 客观下线(ODOWN)
#
3.3 Cluster集群
- 16384个槽位均匀分配
- 去中心化,节点直连
- 哈希槽 = CRC16(key) % 16384
- 支持在线扩容缩容
#
3.4 高频面试题
Q: 主从复制中断后如何恢复?
- 检查偏移量是否在复制缓冲区
- 在缓冲区范围内:增量同步
- 超出范围:全量同步
四、缓存问题
#
4.1 缓存穿透
- 现象:查询不存在的数据,直达数据库
- 解决:布隆过滤器、空值缓存、参数校验
#
4.2 缓存击穿
- 现象:热点Key过期瞬间大量请求打到DB
- 解决:互斥锁、逻辑过期、热点Key永不过期
#
4.3 缓存雪崩
- 现象:大量Key同时过期
- 解决:随机过期时间、多级缓存、熔断降级
#
4.4 缓存一致性
- Cache Aside:先更新DB,再删缓存
- Read/Write Through:读写都走缓存
- Write Behind:先写缓存,异步写DB
五、分布式锁
#
5.1 Redis实现方式
SET key value NX EX seconds- Redisson框架:看门狗自动续期
#
5.2 可靠性要求
- 互斥性:只有一个线程获取锁
- 防死锁:设置过期时间
- 可重入:同一线程可再次获取
- 自动续期:业务未完成时续期
#
5.3 RedLock算法
- 向N个独立Redis节点申请锁
- 多数节点成功且耗时小于超时时间才算成功
- 争议:分布式系统专家质疑其正确性
六、内存管理
#
6.1 内存淘汰策略
| 策略 | 说明 |
|---|---|
| noeviction | 不淘汰,直接报错 |
| allkeys-lru | 所有Key中淘汰最近最少使用 |
| volatile-lru | 过期Key中LRU淘汰 |
| allkeys-random | 所有Key中随机淘汰 |
| volatile-random | 过期Key中随机淘汰 |
| volatile-ttl | 过期Key中淘汰即将过期的 |
| allkeys-lfu | 所有Key中LFU淘汰(4.0+) |
#
6.2 大Key问题
- 危害:阻塞主线程、网络拥塞、主从同步延迟
- 发现:
redis-cli --bigkeys、MEMORY USAGE - 解决:拆分、压缩、异步删除(UNLINK)
#
6.3 内存碎片
mem_fragmentation_ratio = used_memory_rss / used_memory1.5说明碎片严重
- 解决:
MEMORY PURGE、重启
七、性能优化
#
7.1 管道Pipeline
- 批量发送命令,减少RTT
- 注意控制单次Pipeline命令数量
#
7.2 Lua脚本
- 原子性执行多个命令
- 减少网络往返
- 脚本在服务端执行
#
7.3 慢查询优化
# 设置慢查询阈值 |
八、Redis 6.0新特性
- 多线程IO:网络读写多线程,命令执行单线程
- ACL访问控制:细粒度权限管理
- SSL加密:支持TLS连接
- 客户端缓存:Tracking模式
九、与其他组件对比
#
9.1 Redis vs Memcached
| 特性 | Redis | Memcached |
|---|---|---|
| 数据结构 | 丰富 | 仅String |
| 持久化 | 支持 | 不支持 |
| 集群 | 原生支持 | 需客户端 |
| 内存管理 | 更复杂 | 更简单 |
#
9.2 Redis vs Kafka
- Redis Stream适合轻量级消息队列
- Kafka适合高吞吐、持久化场景
十、面试答题技巧
- 由浅入深:先说原理,再讲细节
- 结合场景:回答时结合业务场景
- 承认局限:如RedLock争议、缓存一致性问题
- 展示经验:提到实际排查案例
总结
Redis面试核心围绕:数据类型、持久化、高可用、缓存策略、分布式锁五大主题。理解底层原理比背答案更重要,建议结合源码和实战加深理解。
核心要点
String:简单的键值对,适合缓存、计数器
Hash:存储对象属性,适合用户信息、配置
List:有序列表,适合消息队列、最新列表
Set:无序去重,适合共同好友、抽奖
ZSet:有序集合,适合排行榜、积分系统
总结
选择合适的数据结构是使用 Redis 的关键。在实际项目中,根据业务需求选择合适的类型,可以提升性能和开发效率。