01. 缓存模式——旁路缓存
旁路缓存(Cache Aside)最常用,流程直接:
查数据:先查 Redis → 有直接回 → 没有查数据库 → 写入 Redis 再回
写数据:先更新数据库 → 删掉 Redis 对应缓存(等下次查询自动重建)
这最稳妥,避免了缓存和数据库不一致的坑。
javascript
// Node.js 旁路缓存示例
async function getUser(id) {
const cacheKey = `user:${id}`;
const cached = await redis.get(cacheKey);
if (cached) return JSON.parse(cached);
const user = await db.query('SELECT * FROM users WHERE id = ?', [id]);
if (user) await redis.setex(cacheKey, 3600, JSON.stringify(user));
return user;
}
// 更新时删缓存
async function updateUser(id, data) {
await db.query('UPDATE users SET ? WHERE id = ?', [data, id]);
await redis.del(`user:${id}`);
}02. 缓存穿透、击穿、雪崩——三大问题
这仨是面试必考、线上常见事故:
缓存穿透——查不存在的数据(如 ID=-1),缓存没有直接打到数据库。攻击者专门构造这种请求能打爆数据库。解决:布隆过滤器,或者查不到也缓存空值(短时间)。
缓存击穿——热点 key 刚好过期,瞬间大量请求涌向数据库。解决:加互斥锁,或者「永不过期」异步刷新。
缓存雪崩——大量 key 同时过期,数据库瞬间被压垮。解决:给过期时间加随机值,避免集中过期。
javascript
// 防穿透:缓存空值
let data = await redis.get(`product:${id}`);
if (data === 'NULL') return null;
if (data) return JSON.parse(data);
const product = await db.findById(id);
if (product) {
await redis.setex(`product:${id}`, 3600, JSON.stringify(product));
} else {
await redis.setex(`product:${id}`, 60, 'NULL'); // 空值也缓存
}
return product;
// 防雪崩:过期时间加随机
const ttl = 3600 + Math.floor(Math.random() * 600);
await redis.setex(key, ttl, value);布隆过滤器防穿透神器——极小的内存判断「某 key 一定不存在」。Redis 4.0+ 有内置布隆过滤器模块。
03. 分布式锁
多台服务器抢同一资源需要分布式锁协调。Redis 的 SETNX 可做简易版,但生产建议用 Redlock 算法或 Redisson 等成熟库。
bash
# 简易分布式锁
SET lock:order:123 "random-value" NX EX 30
# 释放用 Lua 保证原子性(先查再删)
EVAL "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end" 1 lock:order:123 random-value简单 SETNX 锁在 Redis 主从切换时可能丢失(主挂了锁还没同步到从)。Redlock 通过在多个独立 Redis 实例同时加锁来解决。
04. 计数器与限流器
利用 Redis 单线程和原子自增轻松实现计数器和限流器。点赞数、阅读量——INCR 搞定。固定窗口限流——设 key 带过期,每次 INCR 超了就拒绝。滑动窗口限流——用 Sorted Set 记录时间戳,精准控制。
bash
# 固定窗口限流(简单版):1 分钟最多 100 次
INCR rate:api:127.0.0.1
EXPIRE rate:api:127.0.0.1 60
# 滑动窗口限流(精确版)——用 Sorted Set
ZADD rate:api:127.0.0.1 <timestamp> <unique-id>
ZREMRANGEBYSCORE rate:api:127.0.0.1 0 <timestamp减60秒>
ZCARD rate:api:127.0.0.1 # 这分钟内多少次知识测验
第 1/5 题正确 0
缓存穿透指的是什么?
下一节
下一节 性能优化