生产首选API网关层限流(如Spring Cloud Gateway+redis-rate-limiter),按用户ID/接口路径/IP控制QPS,配合熔断降级与布隆过滤器协同防御,并通过Redis缓存命中率、数据库线程数等指标动态校准策略。

用 Sentinel 或网关限流拦截雪崩流量
Redis 雪崩发生时,缓存大面积失效或不可用,请求会像洪水一样涌向数据库。这时候光靠“加随机 TTL”已经晚了,必须在入口处卡住流量——不是防 Redis,是防数据库被冲垮。
常见错误现象:服务没报错,但数据库 CPU 100%、连接池打满、慢查询暴增,接口平均响应从 20ms 涨到 2s+,且持续恶化。
- 生产首选 API 网关层限流(如 Spring Cloud Gateway +
redis-rate-limiter),按用户 ID / 接口路径 / IP 维度控制 QPS,避免单点击穿放大成全局雪崩 - 若无统一网关,可在业务服务入口用
Resilience4j的RateLimiter做本地限流,注意配置timeoutDuration和limitRefreshPeriod,否则超时线程堆积反而拖垮 JVM - 慎用 Nginx 限流:它只能按 IP 或请求频率粗粒度过滤,无法识别“查的是有效商品还是恶意 ID”,容易误伤正常用户
熔断降级要配对使用,不能只开开关
限流只是减量,熔断才是止损。但很多团队只配了 Hystrix 或 Resilience4j 的 CircuitBreaker,却没配好 fallback 逻辑,结果熔断一触发,全返回 500 或空 JSON,用户体验比慢还差。
- 降级策略必须分层:核心接口(如下单)可降级为“提示库存紧张,请稍后重试”;非核心(如商品推荐)直接返回静态兜底数据或空数组
-
CircuitBreaker的failureRateThreshold别设 50%,建议 30%~40%,因为雪崩初期失败率上升极快,等它到 50% 时数据库可能已不可逆过载 - 务必设置
waitDurationInOpenState≥ 30 秒,太短会导致“刚熔断又重试→再失败→再熔断”的抖动循环
空值缓存 + 布隆过滤器不是替代限流,而是协同防御
有人以为加了布隆过滤器就不用限流了,这是典型误解。布隆过滤器防的是穿透(查不存在的 key),而雪崩是大量“存在但已过期”的 key 同时击穿,过滤器对此完全无效。
- 布隆过滤器只在
bloomFilter.mightContain(key)返回false时生效;一旦返回true(哪怕实际不存在),后续流程仍会走缓存 → 数据库,照样可能触发击穿或雪崩 - 空值缓存(
redis.setex("user:123", 60, "NULL"))对雪崩防护作用微弱——它解决的是重复查“同一个不存在 key”,不是“一万个人同时查一万个刚过期的热点 key” - 真正起效的是组合:布隆过滤器拦掉 95% 的恶意穿透 → 剩余合法请求再经网关限流 → 超出部分由熔断器拦截并返回友好降级内容
别忘了监控指标才是限流策略的校准器
限流阈值不是拍脑袋定的。某次雪崩恢复后发现,把订单查询接口限流设成 500 QPS,结果真实峰值是 480,看着很安全,但因未监控 redis_keyspace_hits 和 redis_keyspace_misses,没发现缓存命中率已从 99.2% 掉到 76%,说明大量请求本该走缓存却因 key 集中过期被迫穿透——限流只是掩盖了底层问题。
- 关键监控项必须告警:Redis
keyspace_misses1 分钟突增 300%、数据库Threads_running> 200、网关层rate_limiter_blocked_requests_total持续 > 100/分钟 - 限流规则要支持动态调整:用 Apollo/Nacos 管理
resilience4j.ratelimiter.instances.order-qps.limit-for-period,避免每次改配置都要发版 - 压测时一定要模拟雪崩场景:用脚本批量删掉某类前缀的 key(如
redis-cli --scan --pattern "product:*" | xargs redis-cli del),再看限流+熔断是否按预期生效
CircuitBreaker 还不知道,仍在尝试调用数据库。这种割裂会让兜底策略形同虚设。










