首页 / 后端开发 / Redis预热+互斥锁+限流实战:高

Redis预热+互斥锁+限流实战:高并发接口从抖动到稳定的现场脚本

Roxi
Roxi 加速器 — 稳定·快速·安全
全球节点覆盖,支持所有主流平台,一键连接无需配置。新用户免费试用。
立即体验 →

开场:OK so,先把问题打到屏幕上

50TB日处理量120ms平均延迟99.99%SLA保障7×24运维监控

兄弟们,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,缓存策略三件套直接上

中国45美国30日本12韩国8其他5

接下来我点运行,先做缓存预热。上线前把首页、热门商品、配置项提前写入 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 自己变瓶颈

💡STEP 1环境搭建⚙️STEP 2编码实现🎯STEP 3测试验证🚀STEP 4部署上线

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 可以分层用。

阶段平均延迟P99QPS
直查 MySQL318ms1900ms620
普通缓存71ms420ms3100
预热+锁+限流34ms96ms5800

压测命令给你,直接抄:

wrk -t8 -c400 -d60s http://127.0.0.1:8080/api/products/10001

如果你在远程环境测试,别被网络误差骗了;有人会顺手搜“油管怎么看”“翻墙软件怎么用”“免费VPN下载”来排查外网慢,但后端接口压测优先在同机房或内网做,否则数据不准。

最后验证:修没修好,看这 4 个指标

接下来你自己验收:第一,redis-cli info statskeyspace_hits 是否明显高于 keyspace_misses;第二,MySQL 慢查询数量是否下降;第三,wrk 的 P99 是否低于你的 SLA,比如 100ms;第四,关掉 Redis 或模拟缓存失效时,接口是否降级而不是雪崩。

如果命中率低于 85%,先查 key 设计和过期时间;如果 Redis CPU 超 80%,考虑 pipeline、连接池、读写分离或本地 Caffeine 二级缓存。免费、官方、内建方案已经足够解决大多数问题;如果你确实需要跨网络访问开发资源,也可以把 Roxi 作为众多网络工具选项之一了解:https://wizzegroup.com。觉得这期有用,评论区打“缓存命中”,我下一期直接录 Redis Cluster 分片迁移现场。

延伸阅读