一、流量暴涨时,系统在经历什么?
故障定位思路
Redis看似简单,真正落地时却很容易踩坑。假设你运营一个抢票平台,某热门演唱会开售瞬间,10 万用户同时点击「抢票」。如果所有请求直接打到数据库,数据库瞬间就会被请求淹没,连接池耗尽、锁冲突、响应超时——最终页面白屏,用户骂声一片。
这种场景下,真正的问题不是机器不够强,而是流量在极短时间内集中爆发。系统的处理能力(比如每秒能处理 1000 个请求)远低于瞬间涌入的流量(比如每秒 10 万)。解决思路有两个:一是让流量排队慢慢消耗(削峰),二是把多余的流量直接挡在外面(流控)。而实现这两点的核心工具,就是缓存。
二、先搞懂三个核心概念:缓存、削峰、流控
1. 缓存是什么?为什么能“扛”流量?
缓存就是把数据放到一个读取更快的存储里,让下次请求直接从这里取,不用每次都去数据库。好比你把常用工具从仓库(硬盘)拿到桌面(内存),取用速度提升几十倍。缓存可以放在多个层次:浏览器缓存、CDN 边缘节点、应用层本地缓存、分布式缓存(如 Redis)。每一层都能分担一部分请求压力。
2. 削峰,就是把洪峰切成涓涓细流
想象一个水龙头,如果突然把阀门开到最大,下面的杯子瞬间就满了。削峰就是在水管中间加一个缓冲区(比如一个水桶),水先流进水桶,然后以稳定的速度流到杯子里。对应系统里,就是把瞬间海量请求先缓存起来,再按照后端能承受的速率慢慢处理。Redis 因其纯内存操作、高吞吐、丰富的数据结构,常被用作这个“缓冲区”。
3. 流控(限流),就是直接关闭多余的水龙头
当缓冲区也快满的时候,就需要在前端拦住新请求,直接返回“稍后重试”或排队页面。流控的常用算法有令牌桶(匀速发放令牌,拿到才能访问)和漏桶(请求先进入桶,以固定速率流出,超出桶容量的丢弃)。
想继续深入:此处可内链到“Redis优化清单”文章。
三、多级流控与削峰架构:四层缓冲,层层拦截
典型的高并发架构会设置多级缓存,每一级都有自己的角色和阈值。下面按请求从客户端到服务端的路径来看。
第一层:客户端和 CDN 缓存
对于静态资源(图片、CSS、JS),浏览器会主动缓存。如果资源没变,甚至不需要发请求到服务器。CDN(云端内容分发网络)把资源缓存到离用户最近的节点,请求到 CDN 就返回,完全不经过源站。这层能挡住大量重复的静态资源请求,是成本最低的削峰手段。
第二层:反向代理/网关层的限流
请求到达服务器之前,先经过 Nginx 或 API 网关。这里可以配置基础的 IP 限流、用户限流,拦截掉爬虫或异常流量。比如 Nginx 的 limit_req 模块,按每秒允许的请求数控制,超过的请求直接返回 503。这层相当于最外层的“水龙头开关”。
第三层:本地缓存 + Redis 分布式缓存
这是核心层。对于每个应用服务器,可以在内存中维护一份本地缓存(如 Guava Cache),存放热点数据(比如某商品的库存信息)。本地缓存速度最快(微秒级),但容量小,且各服务器之间不一致。对于更多热点数据,通过 Redis 实现全局共享缓存。
削峰的具体做法是:将用户请求(比如下单)先写入 Redis 的一个队列(List 结构),然后由一个后台 worker 以稳定的速度从队列中取出请求,写入数据库。这样数据库永远只收到它能处理的请求数。如果队列满了,就触发流控,让新请求排队等待或直接拒绝。
限流也可以利用 Redis:用 INCR 和 EXPIRE 实现滑动窗口计数器,比如每个用户每秒最多 5 次请求,超过则拒绝。相比单机限流,Redis 限流可以跨服务器生效。
第四层:数据库写缓冲与读写分离
如果 Redis 队列也扛不住了,最后一道防线是数据库本身。通常使用写库 + 读库分离,写库只处理核心写入,读库分担查询压力。还可以引入消息队列(如 RabbitMQ、Kafka)作为更持久的削峰层,把请求异步化。
补充参考:此处可内链到“Redis故障排查实例”。
四、一个完整的例子:秒杀抢购流程与Redis
实际操作要点
假设系统每秒能处理 1000 个订单,但突然来了 10 万用户抢购。架构工作如下:
- 用户点击抢购,请求先到达 Nginx,Nginx 按 IP 限流,每个 IP 每秒最多 1 次,直接过滤掉 80% 的重复请求和刷子。
- 通过 Nginx 的请求进入应用服务器,应用服务器先查本地缓存是否还有库存(本地缓存每秒同步一次 Redis)。如果本地缓存无库存,直接返回“已售罄”。
- 如果本地缓存显示有库存,应用将抢购请求写入 Redis 的 List(比如
seckill_orders),同时用DECR命令扣减 Redis 中的库存(原子操作)。这一步是关键削峰,请求不会直接写数据库。 - 后台 worker 从 Redis List 中 pop 出订单,以每秒 1000 笔的速度写入数据库。数据库只看到平稳的流量,不会被打垮。
- 如果 Redis List 长度超过阈值(比如 10000),说明排队太长,新请求直接返回“排队人数过多,请稍后重试”。这就是流控。
整个过程依赖云端缓存(CDN 挡静态资源)和 Redis 分布式缓存(挡动态请求),实现了完整的削峰降负载。
五、云端缓存与 Redis 部署的注意事项
1. Redis 本身也是资源,不能无限堆请求
Redis 是单线程模型,虽然每秒能处理几万到十几万请求,但每个命令执行时间很短。如果每个请求都放 Redis 做复杂计算(比如大 key 操作),Redis 也会成为瓶颈。所以尽量用简单命令,避免慢查询。
2. 缓存一致性:脏数据怎么办?
多级缓存最容易出现数据不一致。比如 Redis 里的库存和数据库里的库存出现偏差。解决办法:更新数据库时,先删除 Redis 缓存,让下一次请求重新加载。对于最终一致性要求高的场景,可以使用 Canal 监听 MySQL binlog 同步更新缓存。
3. 云端缓存的选型
如果使用云服务(阿里云 Redis、腾讯云 Redis),可以自动处理主从、备份、扩容。注意选择性能规格:对于高并发写场景,建议选用内存版(非混合存储)且开启直连模式;阅读量极大时,可以搭配本地缓存进一步摊薄 Redis 压力。
4. 流控的降级与熔断
当流量超过系统上限时,除了限流,还需要降级:比如关闭非核心功能(排行榜、详情页的推荐),确保核心交易链路的稳定。熔断则是当 Redis 或数据库出现故障时,快速返回兜底数据,防止雪崩。
关联教程:此处可内链到“Redis部署与验证”内容。
六、总结:没有银弹,但多级缓存是最成熟的打法
先看关键判断
高并发系统从来不是靠某一个组件撑起来的,而是靠层层缓冲、步步拦截。云端缓存(CDN)解决静态流量,Redis 分布式缓存解决热点读写和削峰,本地缓存解决极热数据的快速访问,再加上限流算法做最外层保护。理解这套架构背后的思路——把瞬时的大流量拉平,变成持续的小流量——比记住具体命令更重要。
下次你看到某个系统在秒杀时平稳运行,可以默念:它体内可能正跑着一套多级缓存流控系统,Redis 在默默排队,本地缓存正在快速响应,CDN 在边缘挡掉了大部分请求。这就是现代高并发架构的魅力。
延伸阅读
