如果你的系统的 QPS 突然提升 10 倍,你会怎么设计?

 (点个赞,算法会给你推荐更多类似干货 ~)

一、口诀:

QPS 突增莫慌张,分层设计来扛;

CDN 流量WAF 恶意

网关限流服务降级

缓存多级建,数据分片存;

监控全链路,预案提前备。

二、生活例子

场景:火锅店突然涌入 10 倍客人(从 100 人 / 小时 → 1000 人 / 小时)

1、门口拦截:

保安(CDN):引导客人先看菜单(静态资源),避免全挤到收银台

迎宾(WAF):拦住闹事的人(恶意请求),只放正常客人进入

2、店内分流:

取号机(限流):限制同时进入的人数(如最多 100 人在店)

服务员(熔断):告诉客人甜品供应完了(非核心业务熔断)

3、后厨优化:

预制菜(缓存):热门菜提前切好(本地缓存),直接下锅

多灶台(分库分表):把一个大厨房拆成 10 个小厨房(分库),每个负责一类菜

4、供应链保障:

实时补货(弹性伸缩):发现食材快用完,立即通知供应商加送

三、答案:

(1)微服务的拆分
(2)高性能 RPC
(3)消息队列削峰解耦
(4)三级缓存架构
(5)分库分表
(6)高可用
a)熔断
b)限流
c)降级
d)预案
e)核对

1. 分层应对策略

(1)流量拦截层

1)CDN:静态资源全量缓存(命中率需 > 90%),动态内容走网关

2)WAF:实时拦截恶意请求(如 CC 攻击),规则动态更新

3)验证码:人机识别,防爬虫和自动化工具

(2)流量控制层

1)网关限流:按用户 / IP / 接口限流(如单机 5000QPS → 集群 50 万 QPS)

2)熔断降级:非核心业务直接熔断(如评论、推荐),SLA 降级到 90%

3)削峰填谷:消息队列异步处理(如订单创建),最大堆积量需评估

(3)缓存层

1)多级缓存:本地缓存(Caffeine)+ 分布式缓存(Redis 集群)

2)热点数据:预加载到本地缓存,Redis 用读写分离集群(主节点写,从节点读)

3)缓存失效策略:LRU+TTL 结合,避免缓存雪崩

(4)数据层

1)分库分表:单库 10 万 QPS → 拆分为 10 个库,每个库 1 万 QPS

2)读写分离:主库写,从库读(3 个从节点分担读压力)

3)索引优化:覆盖索引减少回表,慢查询自动告警

(5)服务层

1)微服务拆分:按业务领域拆分(如用户、订单、支付),独立扩容

2)RPC 优化:Dubbo(高性能)替代 Feign(适合中小流量),压缩请求体

3)异步化:非关键路径用 MQ 异步处理(如日志记录、短信通知)

2. 技术选型细节

RPC 框架:

Feign → Dubbo:Dubbo 吞吐量约为 Feign 的 3 倍(实测数据),且支持连接池复用、异步调用

协议优化:默认 HTTP/1.1 → gRPC(二进制协议,性能提升 50%+)

消息队列:

RocketMQ → Kafka:Kafka 吞吐量更高(单集群可达百万 QPS),适合纯异步场景

配置优化:Kafkaacks=0(牺牲少量可靠性换极致性能),批量发送(batch.size=16384)

数据库:

MySQL → TiDB:TiDB 支持水平扩展,单集群可支撑百万 QPS(需分表 1000+)

缓存穿透防护:布隆过滤器拦截不存在的 key

3. 监控与预案

全链路监控:

调用链:Skywalking/Zipkin 实时追踪,定位性能瓶颈

指标监控:QPS、RT、错误率,阈值动态调整(如 RT>200ms 自动熔断)

应急预案:

降级开关:通过配置中心(如 Nacos)动态关闭非核心功能

熔断策略:Sentinel 熔断规则(如接口错误率 > 5% 自动熔断)

弹性伸缩:云服务器 ECS 根据负载自动扩缩容(需提前压测确定资源模型)

点赞多,会持续更新!

<think>嗯,用户想设计一个支持百万级QPS的分布式限流系统,这确实是个挑战。首先得理解高QPS下的系统压力,传统的单点限流可能无法应对,所以需要考虑分布式方案。用户提到的引用里提到了Redis+Lua、分片式限流,还有Redisson的实现,这些可能需要结合起来。 首先,系统架构方面,可能需要分层设计,比如客户端、网关层和服务端的分片限流。客户端限流可以减少对后端压力,但需要确保流量均衡,否则可能不均匀。网关层可以用像Sentinel这样的中间件集中管理,但百万QPS的话,网关本身会成为瓶颈,可能需要集群部署,同时用一致性哈希来分配请求。 然后,算法选择,令牌桶适合突发流量,漏桶则平滑,高QPS可能更适合令牌桶,但分布式环境下如何同步令牌数?Redis的原子操作可能不够,因为百万QPS下Redis的吞吐量可能不够,可能需要分片存储或者本地缓存结合异步同步。引用里提到的分片式限流,比如每个节点管理一部分限流,这样总分片数相加可以达到更高QPS,但需要协调分片策略,确保流量正确分配到各节点。 数据存储方面,Redis Cluster可以横向扩展,但Lua脚本的执行需要保证原子性,可能需要每个分片处理自己的限流计数,避免跨节点操作。不过这样分片间的数据一致性会有问题,可能需要最终一致性,或者容忍一定的误差。比如,每个节点有自己的计数器,定期同步到中心存储,但这样在短时间内可能超过全局限制,需要权衡。 性能优化方面,本地缓存+异步上报可以减轻中心存储的压力,比如在客户端或网关层维护本地计数器,每隔一段时间同步到Redis,这样即使有短暂超出,也能在下一周期调整。但时间窗口的精度会受影响,可能需要滑动窗口算法来更精确控制。 容灾和降级也很重要,限流系统本身不能成为单点故障,需要熔断机制,当Redis不可用时,可以降级到本地限流,虽然可能不够准确,但保证系统可用性。另外,动态配置是必须的,能够实时调整限流阈值,应对流量波动。 开源方案中,Sentinel支持集群限流,可能需要结合其Token Server模式,将限流决策集中处理,但扩展性可能受限。而Bucket4j适合客户端集成,结合Redis进行分布式计数,但同样需要考虑Redis的性能瓶颈。 可能的问题包括如何在高并发下保证原子操作,比如使用Redis的INCR和EXPIRE命令,结合Lua脚本确保原子性。另外,分片策略的设计,比如按用户ID哈希分配到不同分片,确保同一用户的请求由同一分片处理,避免跨分片计数。 还要考虑监控和报警,实时跟踪限流状态,及时发现瓶颈。比如Prometheus收集指标,Grafana展示,自动调整限流参数。 总之,设计这样的系统需要结合分层限流、高效算法、分片存储、本地缓存和异步同步,同时保证高可用和容灾能力,可能需要综合多种技术方案,并进行性能测试和调优。</think>### 设计支持百万级 QPS 的分布式限流系统架构及实现方法 #### 一、核心架构设计 1. **分层限流策略** - **客户端限流**:在客户端或 SDK 层实现基础限流逻辑(如计数器或令牌桶算法),过滤无效请求[^2]。 - **网关层限流**:通过 API 网关(如 Nginx + Lua、Envoy、Sentinel)实现全局流量控制,支持滑动窗口、令牌桶等算法[^1]。 - **服务端分片限流**:将限流规则按分片键(如用户 ID、IP 哈希)分布到不同节点,单节点处理局部流量,总分片数满足百万级 QPS[^1][^2]。 2. **算法选择与优化** - **高吞吐场景**:优先选择时间复杂度为 $O(1)$ 的算法(如固定窗口、令牌桶)。 - **精度与平滑性**:采用滑动窗口 + 时间片细分(如 1 秒拆分为 10100ms 子窗口)平衡性能与精度[^1]。 - **分布式一致性**:通过 Redis Cluster 的 `INCR` + `EXPIRE` 实现原子计数,或使用分片限流避免跨节点竞争[^3]。 #### 二、关键技术实现 1. **数据存储与计算分离** - **计数器存储**:Redis Cluster 横向扩展,通过 Pipeline 批量操作减少网络开销,单节点 QPS 可达 10 万级。 - **本地缓存降级**:节点维护本地计数器并异步上报,防止中心存储故障(最终一致性)[^3]。 2. **高性能限流判断逻辑** ```python # 伪代码:基于 Redis 的令牌桶算法实现 def acquire_token(rate, capacity, key): now = time.time() tokens_key = f"{key}:tokens" timestamp_key = f"{key}:timestamp" # 使用 Lua 脚本保证原子性 lua_script = """ local tokens = tonumber(redis.call('get', KEYS[1])) or ARGV[2] local last_refill = tonumber(redis.call('get', KEYS[2])) or 0 local now = tonumber(ARGV[1]) local interval = now - last_refill if interval > 0 then local new_tokens = math.min(ARGV[2], tokens + interval * ARGV[3]) redis.call('set', KEYS[1], new_tokens) redis.call('set', KEYS[2], now) tokens = new_tokens end if tokens >= 1 then redis.call('decr', KEYS[1]) return true end return false """ return redis.eval(lua_script, 2, tokens_key, timestamp_key, now, capacity, rate) ``` #### 三、性能优化手段 1. **批量预取机制**:客户端批量获取令牌(如每次预取 100 个),减少与限流服务器的交互频率。 2. **异步统计上报**:通过内存队列异步聚合统计数据,降低中心存储压力。 3. **分片路由策略**:采用一致性哈希算法分配流量,避免热点分片问题。 #### 四、容灾与监控 1. **熔断降级**:当 Redis 不可用时,自动切换至本地限流模式(牺牲全局一致性)。 2. **动态规则推送**:通过配置中心(如 ZooKeeper、Nacos)实时更新限流阈值。 3. **监控指标**:统计 QPS、限流触发次数、延迟分布(P99/P999),使用 Prometheus + Grafana 可视化。 #### 五、开源方案扩展 - **Sentinel 集群流控**:部署 Token Server 集群,通过 RPC 通信协调全局配额。 - **Bucket4j + Redis**:结合分布式存储实现高精度令牌桶算法(需优化 Lua 脚本性能)。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值