Redis 基础

背景与动机#

Redis 是 Java 后端最常用的内存键值数据库,常用于缓存、计数器、会话、排行榜、消息发布订阅。Spring Boot 项目里常通过 JedisLettuce(Spring Data Redis 默认)访问。理解其数据结构、持久化和高可用方案,才能正确做缓存设计与故障处理。

核心原理拆解#

1. Redis 是什么#

  • 基于内存的 NoSQL KV 存储,key 为字节数组(字符串)
  • 单线程处理命令(6.0+ 网络 IO 可多线程,命令执行仍主线程),避免锁竞争
  • 官方标称可达极高 QPS(数据在内存、IO 多路复用)

Java 侧类似 JDBC 标准,常用 Jedis(含连接池 JedisPool)或 Lettuce

2. 五种基本数据结构#

类型说明典型场景
String字符串、数字、二进制JSON 缓存、计数器、点赞数
List双向链表队列、栈、时间线
Hash字段-值映射对象属性、分组
Set无序不重复标签、共同好友
ZSet有序集合排行榜

应用场景示例

  • String:缓存对象、视频点赞计数
  • List:模拟队列;朋友圈内容 + 点赞列表(user:x:post:x + post:x:good
  • Hash:存用户对象字段、按组聚合

3. 为什么单线程还很快#

  1. 数据主要在内存
  2. IO 多路复用(epoll 等),单线程处理大量连接
  3. 无锁竞争,避免上下文切换开销

4. 发布订阅#

Redis 支持 Pub/Sub:发布者发频道,订阅者收消息。实现简单,但无消息堆积与回溯,复杂场景用 Kafka、RocketMQ。哨兵节点也通过频道交换监控信息(约每 2 秒)。

5. 持久化:RDB 与 AOF#

方式原理优点缺点
RDB(默认)bgsave fork 子进程写快照,定时全量文件紧凑,恢复快非实时,fork 有开销
AOF每条写命令追加到日志更实时文件大,需 rewrite,恢复慢

生产常 RDB + AOF 组合,兼顾恢复速度与数据安全。

6. 主从复制与哨兵(Sentinel)#

主从:主写从读,数据异步复制。

主挂了:手动切换麻烦 → 哨兵模式(2.8+)自动监控与故障转移。

哨兵流程概要

  1. 每 10s INFO 拉拓扑;每 2s 向频道发主观判断;每 1s PING 心跳
  2. 主观下线:某哨兵认为节点不可达
  3. 客观下线:主节点主观下线时,半数以上哨兵同意
  4. 选举领导者:Raft 思想,谁先提出客观下线谁易当选
  5. 故障转移:选举新主节点

7. Redis 集群(3.0+)#

采用虚拟槽(16384 slots),节点间 ping/pong 传播槽与故障信息;主观下线(pfail)→ 客观下线(fail)→ 选举领导者 → 故障转移。与哨兵类似,面向分片 + 高可用,适合大数据量。

8. 缓存与 MySQL 一致性#

常见策略(按业务选,没有银弹):

  • Cache Aside:读先缓存、miss 查 DB 再写缓存;写先更新 DB 再删缓存
  • 过期策略:TTL + 主动失效
  • 双写一致性:延迟双删、Canal 订阅 binlog 等(高一致场景)

9. Key 过期与内存淘汰#

过期删除

  • 惰性:访问 key 时才检查是否过期(省 CPU,可能占内存)
  • 定期:周期性抽样删除过期 key(折中)

因此设置了 5 分钟 TTL,到期后内存仍可能偏高——部分 key 尚未被访问或定期清理未扫到。

内存淘汰策略(内存不足时):

  • noeviction:报错(默认)
  • allkeys-lru / allkeys-random
  • volatile-lru / volatile-random / volatile-ttl(仅带过期的 key)

10. 缓存问题与应对#

问题含义思路
穿透查不存在的数据,缓存和 DB 都不命中,压垮 DB缓存空值(注意 TTL)、布隆过滤器
击穿热点 key 过期瞬间大量请求打 DB互斥锁、逻辑过期
雪崩大量 key 同时过期或缓存宕机,请求涌向 DB过期时间加随机、集群高可用、限流降级
热点 key单个 key QPS 极高本地缓存、多副本、拆分

无底洞:集群节点过多,批量操作跨节点网络次数增加,性能反而下降——控制粒度、使用 hash tag 把相关 key 放同一槽。

11. 缓存粒度#

  • 粗粒度:一个 key 存整页数据,命中率高,更新成本高
  • 细粒度:按字段或实体拆分,更新灵活,key 数量多

按读多写少、更新频率选择。

常见陷阱与错误示例#

1. 把 Redis 当可靠消息队列#

Pub/Sub 不持久化,消费者离线会丢消息;严肃场景用专业 MQ。

2. 缓存空值不设过期#

恶意穿透时大量空 key 占满内存,必须短 TTL。

3. 主从异步复制读从库#

主从延迟时可能读到旧数据,强一致读主或等复制。

面试高频问题#

完整 15 道速查见 Redis 面试题 15 道

一句话总结#

Redis = 内存 + 单线程 + 多路复用;用对数据结构和高可用(主从/哨兵/集群);做缓存时同时设计过期、淘汰、穿透/雪崩/热点和与 DB 的一致性策略。

文章目录

文章目录