Redis 原理与高并发缓存设计

5 阅读3分钟

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

👉 流程:

  1. 先查 Redis
  2. 没有 → 查数据库
  3. 写入 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 多路复用实现高并发处理。在缓存设计中通常采用旁路缓存模式,同时需要解决缓存穿透、击穿和雪崩问题。通过合理的缓存策略和一致性方案,可以显著提升系统性能和稳定性。