三大缓存问题
在高并发场景下,Redis 面临三大经典问题:缓存穿透、缓存击穿、缓存雪崩。理解并正确处理它们是后端开发的必备技能。
1. 缓存穿透
问题:查询不存在的数据,请求直接穿透缓存打到数据库。
解决方案:
- 布隆过滤器:预先标记所有可能的 key
- 缓存空值:对不存在的 key 缓存空标记
// Node.js 示例:缓存空值
async function getProduct(id) {
const cacheKey = `product:${id}`;
let data = await redis.get(cacheKey);
if (data === '__NULL__') return null;
if (data) return JSON.parse(data);
const product = await db.findProduct(id);
if (!product) {
await redis.setex(cacheKey, 60, '__NULL__');
return null;
}
await redis.setex(cacheKey, 3600, JSON.stringify(product));
return product;
}
2. 缓存击穿
问题:热点 key 过期瞬间,大量请求同时打到数据库。
解决方案:互斥锁 / 逻辑过期
async function getWithMutex(key) {
let data = await redis.get(key);
if (data) return JSON.parse(data);
const lockKey = `${key}:lock`;
const locked = await redis.set(lockKey, '1', 'NX', 'EX', 10);
if (locked) {
const fresh = await db.query(key);
await redis.setex(key, 3600, JSON.stringify(fresh));
await redis.del(lockKey);
return fresh;
}
// 等待 50ms 后重试
await sleep(50);
return getWithMutex(key);
}
3. 缓存雪崩
问题:大量 key 同时过期,或 Redis 服务宕机,导致请求全部打到数据库。
解决方案:
- TTL 加随机值:
setex(key, 3600 + Math.random() * 600, value) - 多级缓存:本地缓存 + Redis + DB
- 限流降级:Sentinel 限流 + Hystrix 断路器
4. Sentinel 哨兵模式
# sentinel.conf
port 26379
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 10000
5. Cluster 集群模式
# 启动 6 个节点(3 主 3 从)
redis-server redis7000.conf --cluster-enabled yes
redis-server redis7001.conf --cluster-enabled yes
# ... 共 6 个节点
# 创建集群
redis-cli --cluster create \
127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 \
127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 \
--cluster-replicas 1
总结
理解缓存穿透、击穿、雪崩的成因与解决方案,掌握 Sentinel 和 Cluster 的部署,就能构建稳定可靠的 Redis 缓存体系。