Redis无内置排队机制防击穿,真正有效的是SETNX原子锁+轮询等待策略,而非LPUSH/BRPOP队列,因其会导致无效阻塞、资源争抢和消息丢失风险。

Redis 本身没有内置“排队机制”,所谓“用 Redis 做排队解决击穿”是常见误解——真正起作用的不是队列,而是原子性锁 + 等待策略。击穿本质是并发重建缓存的竞争问题,不是请求积压问题。
为什么不能用 LPUSH + BRPOP 模拟排队防击穿
有人尝试用 LPUSH 把请求塞进 list,再用 BRPOP 阻塞取任务、查库、写缓存,以为能串行化处理。这会导致三个硬伤:
- 每个请求都进队列,但只有第一个需要查库;其余请求本可直接读新缓存,却被卡在队列里白白等待
- Redis list 是全局资源,高并发下
LPUSH/BRPOP争抢严重,反而放大延迟 - 一旦消费者(比如某个 worker)崩溃,队列里积压的请求就永久丢失或超时,无法 fallback 到直查数据库
真正有效的“排队感”来自 SETNX + 轮询
所谓“排队”,其实是让非首请求主动让出 CPU、短暂等待,而不是真进队列。核心是用 SET 的 NX EX 参数一步完成加锁,避免竞态:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
-
SET lock:news:12345 "1" NX EX 30:加锁成功返回OK,失败返回(nil) - 加锁失败者不重试加锁,而是
GET news:12345轮询,间隔建议20ms,总等待上限设为200ms - 轮询期间若
GET返回非空,立即返回;超时则降级为直查数据库,避免雪球效应
逻辑过期比物理过期更适合新闻类热点
新闻详情页(如突发快讯)访问量陡增但更新频次低,用物理 TTL 极易在发布时间点后整点失效。改用逻辑过期更稳:
- 缓存 value 存 JSON:
{"content":"...","expireAt":1725443520},key 本身永不过期 - 读取时先解析
expireAt,若已过期,触发异步刷新(如提交到线程池),当前请求仍返回旧内容 - 必须校验所有服务节点的系统时间偏差
< 2s,否则expireAt判断失准 - 异步刷新失败时,应延长下次逻辑过期时间(如 +60s),避免反复触发
新闻类数据对实时性容忍度较高,逻辑过期配合异步刷新,既能彻底消灭击穿点,又不会拖慢首屏加载——这才是生产环境真正敢放开压测的做法。

















