Redis 原理与高并发缓存设计
一、先说结论
Redis 是基于内存的高性能键值数据库,采用单线程 + IO 多路复用模型,通过减少上下文切换和锁竞争实现高吞吐。常用于缓存、分布式锁和计数器。在高并发场景下需要重点解决缓存穿透、击穿和雪崩问题。
二、Redis 为什么这么快?
🧠 核心原因:
1. 内存操作
2. 单线程模型
3. IO 多路复用
1️⃣ 内存操作
👉 数据在内存:
纳秒级访问
👉 对比 MySQL:
磁盘 IO → 毫秒级
2️⃣ 单线程模型
👉 Redis 是单线程执行命令
👉 为什么反而更快?
1. 没有锁竞争
2. 没有线程切换
3️⃣ IO 多路复用
👉 一条线程同时处理多个连接
👉 常见模型:
select / poll / epoll
三、Redis 常用数据结构(面试必问)
📦 1️⃣ String
最常用
用途:
- 缓存
- 计数器
📦 2️⃣ Hash
key → field → value
用途:
- 用户信息
📦 3️⃣ List
👉 有序列表
📦 4️⃣ Set
👉 去重集合
📦 5️⃣ ZSet(重点)
👉 带分数的排序集合
👉 用途:
🔥 排行榜
四、缓存的基本模型
🧠 常见架构:
请求 → Redis → MySQL
👉 流程:
- 先查 Redis
- 没有 → 查数据库
- 写入 Redis
👉 这叫:
Cache Aside(旁路缓存)
五、高并发三大问题(重点🔥)
❗1:缓存穿透
👉 什么是穿透?
查询一个不存在的数据
👉 流程:
Redis 没有 → 查 DB → 也没有
👉 每次都打 DB
🔥 数据库被打爆
✅ 解决方案:
✔️ 1:缓存空值
key → null(短过期)
✔️ 2:布隆过滤器(高级)
👉 判断 key 是否存在
❗2:缓存击穿
👉 什么是击穿?
热点 key 失效
👉 大量请求同时:
直接打 DB
✅ 解决:
✔️ 1:互斥锁(常用)
if (redis.get(key) == null) {
lock.lock();
try {
// 查 DB
} finally {
lock.unlock();
}
}
✔️ 2:永不过期 + 异步更新
❗3:缓存雪崩
👉 什么是雪崩?
大量 key 同时过期
👉 结果:
🔥 数据库被打爆
✅ 解决:
✔️ 1:过期时间随机
TTL + random
✔️ 2:多级缓存
✔️ 3:限流 / 降级
六、缓存一致性问题(实战重点)
❗问题:
Redis 和 DB 数据不一致
常见方案:
✅ 方案1:先更新 DB,再删缓存(推荐)
update db;
delete cache;
👉 下次查询:
→ 自动更新缓存
❗为什么不先删缓存?
并发可能导致脏数据
✅ 进阶方案:
👉 延迟双删
删除缓存 → 更新 DB → 再删一次
七、Redis 分布式锁(高频)
👉 实现:
SET key value NX EX 10
👉 含义:
- NX:不存在才设置
- EX:过期时间
❗问题:
- 锁失效
- 误删锁
✅ 解决:
- value 用 UUID
- 释放锁校验
八、一个真实业务案例(你能用上)
🎯 场景:商品详情页(高并发)
❗问题:
- 热点数据
- 高 QPS
✅ 方案:
1. Redis 缓存商品数据
2. 热点数据永不过期
3. 后台定时更新
👉 效果:
🔥 扛住大流量
九、一个高级理解(拉开差距)
👉 Redis 单线程为什么还能高并发?
👉 因为:
瓶颈不在 CPU,而在 IO
👉 Redis:
- 避免锁
- 利用 IO 多路复用
👉 本质:
用“简单模型”换高性能
十、总结(面试高分表达)
你可以这样说:
Redis 是基于内存的高性能数据库,通过单线程和 IO 多路复用实现高并发处理。在缓存设计中通常采用旁路缓存模式,同时需要解决缓存穿透、击穿和雪崩问题。通过合理的缓存策略和一致性方案,可以显著提升系统性能和稳定性。