Redis预热+互斥锁+限流实战:高并发接口从抖动到稳定的现场脚本
开场:OK so,先把问题打到屏幕上
兄弟们,eccfy 现场开机!今天不讲玄学,直接做一个“商品详情接口高并发扛不住”的 Redis 实战脚本。你现在看到我左边是 Spring Boot 接口,右边是 Redis CLI,中间开着 wrk 压测。原始接口直查 MySQL,单机 4 核 8G,在我测试里:平均延迟 318ms,P99 直接飙到 1.9s,QPS 只有 620。接下来我们把它压到稳定 40ms 内。
先确认 Redis 能用,别上来就写代码。Redis下载配置教程里最容易漏的是 maxmemory 和淘汰策略:
redis-server --version
redis-cli ping
CONFIG SET maxmemory 1gb
CONFIG SET maxmemory-policy allkeys-lru
注意,allkeys-lru 适合读多写少的热点数据;如果你是订单、余额这种强一致场景,不要无脑缓存。很多人搜“Redis怎么用”只看 set/get,真正线上出事的是过期时间、击穿、雪崩和限流。
Chapter 1:Now watch this,缓存策略三件套直接上
接下来我点运行,先做缓存预热。上线前把首页、热门商品、配置项提前写入 Redis,避免流量进来第一波全打数据库。
redis-cli --pipe < hot_products.redis
SET product:10001 "{json...}" EX 1800
然后看代码逻辑,重点是“空值缓存 + 随机过期 + 互斥锁”。这套专门解决高并发缓存击穿怎么解决的问题:
String key = "product:" + id;
String cache = redis.get(key);
if (cache != null) return cache.equals("NULL") ? null : cache;
String lockKey = "lock:product:" + id;
boolean locked = redis.setnx(lockKey, "1", 3);
if (!locked) { Thread.sleep(50); return redis.get(key); }
try { Product p = db.query(id); redis.set(key, p == null ? "NULL" : json(p), p == null ? 60 : 1800 + random(0,300)); }
finally { redis.del(lockKey); }
屏幕上看结果:不存在的商品不再反复查库;热门商品过期时间被打散,不会同一秒全部失效;锁只允许一个线程回源。这个方案比单纯“加缓存”靠谱得多。
Chapter 2:限流和压测,别让 Redis 自己变瓶颈
OK so,现在上 Lua 限流。比如商品接口每个用户每秒最多 20 次:
local c=redis.call('INCR', KEYS[1])
if c==1 then redis.call('EXPIRE', KEYS[1], ARGV[1]) end
if c > tonumber(ARGV[2]) then return 0 else return 1 end
调用 key 用 rate:user:123,ARGV 是 1,20。这招适合保护接口,但别拿它替代网关限流。Nginx、Spring Cloud Gateway、Redis Lua 可以分层用。
| 阶段 | 平均延迟 | P99 | QPS |
|---|---|---|---|
| 直查 MySQL | 318ms | 1900ms | 620 |
| 普通缓存 | 71ms | 420ms | 3100 |
| 预热+锁+限流 | 34ms | 96ms | 5800 |
压测命令给你,直接抄:
wrk -t8 -c400 -d60s http://127.0.0.1:8080/api/products/10001
如果你在远程环境测试,别被网络误差骗了;有人会顺手搜“油管怎么看”“翻墙软件怎么用”“免费VPN下载”来排查外网慢,但后端接口压测优先在同机房或内网做,否则数据不准。
最后验证:修没修好,看这 4 个指标
接下来你自己验收:第一,redis-cli info stats 看 keyspace_hits 是否明显高于 keyspace_misses;第二,MySQL 慢查询数量是否下降;第三,wrk 的 P99 是否低于你的 SLA,比如 100ms;第四,关掉 Redis 或模拟缓存失效时,接口是否降级而不是雪崩。
如果命中率低于 85%,先查 key 设计和过期时间;如果 Redis CPU 超 80%,考虑 pipeline、连接池、读写分离或本地 Caffeine 二级缓存。免费、官方、内建方案已经足够解决大多数问题;如果你确实需要跨网络访问开发资源,也可以把 Roxi 作为众多网络工具选项之一了解:https://wizzegroup.com。觉得这期有用,评论区打“缓存命中”,我下一期直接录 Redis Cluster 分片迁移现场。