架构 (IT)系统架构师

您将如何设计一个全球一致的、水平可扩展的速率限制服务,该服务在分布式边缘节点之间实施每个用户和每个租户的限流政策,同时在缓存冲击期间防止雷群问题并确保在流量高峰期间的公平性?

用 Hintsage AI 助手通过面试

问题回答

一个分布式速率限制架构需要在地理分散的节点之间平衡强一致性和低延迟。该解决方案利用层次化令牌桶算法,包含以下组件:

• 使用 Redis 集群和 Lua 脚本进行原子令牌消耗的边缘本地执行
• 通过 Apache Kafka 主题进行全球配额协调的跨区域同步
一致性哈希用于用户亲和性,以最小化协调开销

该架构在Redis中实现滑动窗口日志语义,使用有序集合 (ZADD/ZREMRANGEBYSCORE) 进行精确请求跟踪。八卦协议在网络中传播速率限制配置更改,消除政策分配中的单点故障。

生活中的情况

一个全球金融科技平台在黑色星期五流量高峰期间处理 50 万个请求每秒,经历了灾难性的故障。他们现有的集中式 Redis 速率限制器引入了 150ms+ 的延迟,并成为单点故障,导致支付服务出现级联超时。

最初考虑的解决方案是在每个 NGINX 边缘节点上纯粹进行本地速率限制。这种方法提供了亚毫秒的延迟,并消除了网络依赖。然而,它允许用户超出配额的倍数等于边缘位置的数量,违反了业务合规要求,并可能在分布式基础设施上导致滥用。

第二种方法评估了一个集中式 Redis 集群,使用 Redlock 进行分布式锁定。虽然这确保了完美的一致性,但为国际用户创造了不可接受的延迟,并引入了关键的网络分区漏洞。在区域间连接问题期间,该系统面临完全降级而不是优雅降级。

第三种解决方案实施了混合的滑动窗口计数器,使用最终一致性CRDTs(无冲突复制数据类型)。这提供了速率限制收敛的数学保证,而无需协调。然而,在分区事件期间,它允许临时配额违反,这对于需要严格支出控制的财务合规是不可接受的。

选择的架构采用了 双层速率限制:在边缘节点上使用具有 TTL 的桶的严格本地执法,结合通过 Kafka 流进行异步协调以实现全球配额执行。一致性哈希 将用户路由到特定区域集群,确保 95% 的请求无需跨区域协调。这平衡了对即时地方执行的需求与最终全球一致性的需求。

实施将 P99 延迟从 150ms 降低到 8ms,并在没有降级的情况下处理 10 倍的流量高峰。该系统在网络分区期间优雅降级,允许本地执行继续进行,稍微放宽全球限制,在区域中断期间保持服务可用性。

候选人常常忽视的内容

当使用令牌桶算法而没有集中协调时,您如何处理分布式速率限制器之间的时钟偏差?

时钟同步代表了分布式速率限制系统的无声杀手。当边缘节点经历 NTP 漂移时,令牌桶计算变得不准确,可能允许请求突发超过配置的限制或人为限制合法流量。解决方案需要通过 Lamport 时间戳混合逻辑时钟 结合漂移容忍缓冲来实现 逻辑时钟。每个令牌补充操作应包括单调时间戳验证,拒绝时间戳差异超过配置阈值(通常为 100-500ms)的补充请求。这在保持可用性的同时防止可利用性,同时在轻微的时钟偏差事件期间保持可用性。

在高并发环境中,当速率限制计数器到期时,有哪些策略可以防止雷群场景?

雷群现象发生在数千个请求同时发现过期的速率限制密钥并尝试并发补充,从而压垮后端的 Redis 实例。标准的 Lua 脚本用于原子增量解决了基本的竞争条件,但无法防止密钥过期期间的踩踏。实施概率性提前过期(也称为抖动),其中每个请求有一个小概率(通常为 1%)在实际过期之前稍微重新生成令牌桶。或者,使用Redis Cell模块或Redis流与XADD操作,将速率限制视为时间序列数据,而不是简单计数器。这将雷群现象转变为平滑的、错开的再生模式,而不会增加应用层的代码复杂性。

当一个租户主导请求量,可能使共享速率限制基础设施中的其他租户饥饿时,您如何确保公平性?

公平性要求实施加权公平排队 (WFQ) 或 层次化令牌桶 (HTB) 算法,而不是简单的每租户固定限额。在一个多租户的 Kubernetes 环境中,考虑使用带有本地速率限制过滤器的 Envoy Proxy,结合自适应并发控制。关键的见解是将 执行点决策点 分开:使用边车模式,其中 Envoy 基于缓存的权重处理立即拒绝,而运行 etcd 的中央 控制平面 定期根据历史消耗模式重新计算权重。这避免了嘈杂的邻居问题,同时确保突发但合法的租户仍可以在非高峰期访问资源。