SELECT COUNT(*) FROM access_log WHERE uri = '/seckill' AND created_at BETWEEN '2026-03-01 10:00:00' AND '2026-03-01 10:00:03'; # 2000 个请求里 1900 个返回 429
秒杀 10 点整开始,桶容量 100 补充速率 100/s。10:00:00 这一秒进来 2000 个请求,前 100 个通过,后面 1900 个返回 429,持续 3 秒才恢复,用户看到的是瞬间全灭。先别急着动参数,把报错原文和时间点记下来,顺序反了容易白折腾。
原因不复杂,令牌桶只在请求到来时计算补充,1 秒内的突发没有任何排队,桶空后直接拒绝。容量按平均 QPS 设的,没按峰值并发估。
围绕「突发流量打穿限流」排查时,命令行跑一遍比在面板里点十次有用,面板会替你做掉不少隐式操作。动手前把原文件复制一份带时间戳,出问题立刻换回去,比现场分析快得多。
一次只改一处,改完立刻验证,几个改动叠在一起,出问题就说不清是谁导致的。
处理上按这个顺序:容量按峰值并发设 至少覆盖 1 秒的突发;超出的请求进队列等待 不要直接拒 设一个最大等待时间;秒杀前置一层预约或排队 把瞬时并发摊平。
改完只确认一件事:同样的 2000 并发下通过率从 5% 提到 90%,429 集中在 200 毫秒内不再持续 3 秒。
