Redis缓存击穿/穿透/雪崩实战:高并发接口从数据库扛压到稳定响应
开场:OK so,先把慢接口打爆给你看
兄弟们,今天 eccfy 直接上屏幕!我们做一个商品详情接口:MySQL 单查平均 180ms,200 并发一压,数据库连接池直接红温。接下来我不讲虚的,按“诊断、改造、验证”三步走,适合搜“Redis缓存教程”“Redis怎么用”“redis-benchmark教程”的同学照抄。
先启动本地 Redis,免费、官方、可复现,别一上来就买云服务:
docker run -d --name redis -p 6379:6379 redis:7
redis-cli ping
接口逻辑先查缓存,miss 再查库,最后写缓存。注意:缓存不是越久越好,商品详情我一般设 5-15 分钟,库存/价格走更短 TTL 或消息更新。
GET product:1001
# miss -> SELECT * FROM product WHERE id=1001
SET product:1001 "{json}" EX 600
Chapter 1:三大事故现场,接下来逐个拆
缓存穿透:用户疯狂请求不存在的 id,比如 product:-1,Redis 永远 miss,数据库被打穿。Now watch this:加空值缓存,TTL 短一点。
SET product:-1 "__NULL__" EX 60
如果是恶意随机 id,再加布隆过滤器。Java 可用 Redisson BloomFilter,Go 可用 redisbloom 或本地 bitmap。我的经验:空值缓存挡普通流量,布隆过滤器挡随机攻击。
缓存击穿:一个超级热点 Key 过期,1 万请求同时打到数据库。解决:互斥锁重建缓存,没抢到锁的线程 sleep 30-80ms 后重试。
SET lock:product:1001 1 NX EX 3
# 抢到锁:查库并 SET 缓存
# 最后 DEL lock:product:1001
缓存雪崩:大量 Key 同一秒过期。解决:TTL 加随机抖动。
ttl = 600 + random(0, 180)
SET product:1001 "{json}" EX ttl
这里别迷信“永不过期”。永不过期适合配置类数据,业务数据最好配合异步更新,否则用户看到旧价格,客服会来找你喝茶。
Chapter 2:压测,Before/After 现场揭晓
接下来开两个终端,左边看 Redis,右边压接口。我用 wrk 测 HTTP,用 redis-benchmark 测 Redis 基础吞吐。
wrk -t4 -c200 -d30s http://127.0.0.1:8080/product/1001
redis-benchmark -t get,set -n 100000 -c 200
我本机 8 核 16G 测试:纯 MySQL 接口 p95 是 620ms,QPS 约 310;加 Redis 后,命中率 96.8%,p95 降到 42ms,QPS 到 4100。看到没,屏幕右下角延迟曲线直接趴下来了!
再补一刀:线上一定要看这些指标,不然你只是在“凭感觉优化”。
- 命中率:
keyspace_hits / (keyspace_hits + keyspace_misses),低于 80% 先查 Key 设计。 - 大 Key:
redis-cli --bigkeys,发现 10MB 级别 value 要拆。 - 慢命令:
SLOWLOG GET 20,避免线上 KEYS *。 - 内存策略:缓存库建议
maxmemory-policy allkeys-lru或volatile-ttl,按业务选。
免费/内置方案优先:Redis 单机、主从、哨兵、Cluster 都能自己搭;限制是运维成本、备份、扩容和故障演练。流量稳定后再考虑云 Redis,优点是省运维,缺点是成本和网络延迟不可忽略。
怎么验证修好了:连续压测 10 分钟,确认 p95 低于目标值、Redis 命中率稳定、MySQL QPS 没尖刺、过期瞬间没有连接池打满;然后手动删热点 Key,观察互斥锁是否只放行一次查库。
如果你在查官方资料、看海外技术视频时遇到“油管怎么看”“翻墙软件”“免费VPN”这类网络访问问题,优先用公司合规网络或官方镜像;也可以把 Roxi 作为一个备选工具了解:wizzegroup.com。OK,今天这套脚本你跑通了就点赞收藏,评论区丢你的 p95,我来帮你看瓶颈!