← 2026-06-15 📂 All Days 2026-06-17 →

🏗️ 系统设计 / System Design — Day 67

主题 / Topic: Design a Rate Limiter as a Service

难度 / Difficulty: Advanced | 阶段 / Phase: Expert

预计阅读 / Read time: ~3 min


🏗️ 系统设计 / System Design

设计一个限流服务 / Design a Rate Limiter as a Service


场景 / Scenario

想象你在 Stripe 基础设施团队。每秒有数百万个 API 请求打到你们的系统,客户的代码 bug、恶意爬虫、或者流量突增随时可能压垮下游服务。你需要设计一个分布式限流服务,支持多种算法、多级限流(按用户、按 IP、按 API key),且延迟必须在 1ms 以内。

Imagine you're on Stripe's infrastructure team. Millions of API requests hit your system every second — buggy client code, malicious scrapers, and traffic spikes can take down downstream services at any moment. Design a distributed rate limiter service with multiple algorithms, multi-level limiting (by user, IP, API key), and sub-1ms latency.


🏛️ 架构图 / Architecture Diagram

┌─────────────────────────────────┐ │ API Gateway │ │ (Nginx / Envoy / Kong) │ └──────────────┬──────────────────┘ │ ┌─────────▼─────────┐ │ Rate Limiter │ │ Sidecar / SDK │ │ │ │ 1. Check limit │ │ 2. Increment ctr │ │ 3. Return allow/ │ │ deny + headers │ └────────┬──────────┘ ┌───────────┼───────────┐ │ │ │ ┌───────▼──┐ ┌─────▼────┐ ┌───▼──────┐ │ Redis │ │ Redis │ │ Redis │ │ Cluster │ │ Cluster │ │ Cluster │ │ (Shard1) │ │ (Shard2) │ │ (Shard3) │ └──────────┘ └──────────┘ └──────────┘ │ │ │ ┌───────▼───────────▼───────────▼───────┐ │ Config Service │ │ (limits per API key / IP / user) │ │ Stored in DB, cached in Redis │ └─────────────────────────────────────────┘

⚙️ 核心算法对比 / Algorithm Comparison

四种主流限流算法 / Four main algorithms:

算法优点缺点适用场景
Token Bucket 令牌桶允许突发流量实现稍复杂API 限流(最常用)
Leaky Bucket 漏桶平滑输出不允许突发流媒体、网络
Fixed Window 固定窗口简单,O(1)边界突发问题简单场景
Sliding Window Log 滑动日志精确内存占用大精确计费
Sliding Window Counter 滑动计数近似精确+高效有误差生产推荐 ✅

Redis 实现 — 滑动窗口计数 / Redis Sliding Window Counter:

import redis
import time

r = redis.Redis()

def is_allowed(key: str, limit: int, window_seconds: int) -> bool:
    now = time.time()
    window_start = now - window_seconds
    
    pipe = r.pipeline()
    # Remove old entries outside the window
    pipe.zremrangebyscore(key, 0, window_start)
    # Add current request
    pipe.zadd(key, {str(now): now})
    # Count requests in window
    pipe.zcard(key)
    # Set expiry to avoid memory leak
    pipe.expire(key, window_seconds + 1)
    results = pipe.execute()
    
    count = results[2]
    return count <= limit

# Usage
key = f"rate_limit:user:{user_id}:api_key:{api_key}"
if not is_allowed(key, limit=100, window_seconds=60):
    return 429, {"Retry-After": 60}

⚖️ 关键权衡 / Key Tradeoffs

1. 本地缓存 vs 完全依赖 Redis

  • 方案A:每次请求都查 Redis → 精确,但 +0.5-1ms 延迟
  • 方案B:本地缓存 + Redis 异步同步 → 快,但允许小幅超限(~1-5%)
  • 生产选择: 方案B,通过软限制 + 硬限制双层实现(本地 soft limit 95%,Redis hard limit 100%)

2. 分布式 Race Condition

  • 问题:多个节点同时读写同一个计数器可能超限
  • 解决:Redis Lua 脚本原子操作(EVAL),或用 Redis INCR + EXPIRE 组合

3. 多维度限流优先级

API Key Level → 10,000 req/min └── User Level → 1,000 req/min └── IP Level → 100 req/min

按最严格的维度拒绝,返回对应的 X-RateLimit-* headers。


❌ 常见坑 / Common Mistakes

  1. 固定窗口的边界突发:如果窗口 0:59 来 100 次,1:01 再来 100 次,两秒内实际 200 次但都算合法。用滑动窗口解决。
  2. 没有降级机制:Redis 挂了怎么办?应该有 fail-open(放行)vs fail-closed(拒绝)的配置,通常选 fail-open 避免影响业务。
  3. 忘记返回标准 headers:X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, Retry-After

📚 深入阅读 / References

  1. System Design: Rate Limiter — Alex Xu DDIA-style
  2. Redis Rate Limiting Patterns
  3. Stripe's Rate Limiting Approach

🧒 ELI5

限流就像超市收银台排队:每分钟只能结 100 个人,超了就让你等一会儿,不是不让你来,只是让你稍等。

Rate limiting is like a checkout line: only 100 people per minute, extras just wait — you're not banned, just slowed down.

💻 算法 / Algorithms — Day 67

题目 / Problem: #98 Validate Binary Search Tree (Medium)

模式 / Pattern: 树遍历模式 (Trees) — 第 11/15 题

预计阅读 / Read time: ~4 min


💻 算法 / Algorithms

🧩 树遍历模式 (11/15) — building on the template from Day 56

这是 Trees 板块第 11 题,我们已经掌握了 DFS 递归框架。今天的关键是:BST 验证不是每个节点和左右孩子比,而是和整棵子树的范围比。

We're 11/15 into the Trees block. Today's key insight: BST validation isn't comparing a node to its direct children — it's checking against the valid range of the entire subtree.


🔗 Links


🌍 现实类比 / Real-World Analogy

想象你在验证一棵公司组织架构:CEO 薪资必须高于所有下属,且每一层的薪资范围都有上下限约束。不是只看"老板比直属下属高"就够了——你得确保整条链路都满足范围约束。

Like verifying salary hierarchy in an org chart: it's not enough that a manager earns more than direct reports — every node must fit within valid bounds for its entire chain.


🗺️ 映射到模版 / Map to Template

# 基础模版
def dfs(node):
    if not node: return BASE_CASE
    left = dfs(node.left)
    right = dfs(node.right)
    return COMBINE(node.val, left, right)

# 今天的变体:传入范围边界
# Today's variation: pass valid range bounds down
def dfs(node, min_val, max_val):
    if not node: return True  # BASE_CASE = valid
    if not (min_val < node.val < max_val):
        return False
    left = dfs(node.left, min_val, node.val)   # must be < node.val
    right = dfs(node.right, node.val, max_val) # must be > node.val
    return left and right                       # COMBINE

与之前题目的区别 / What's different from previous problems:

  • Day 56 (Max Depth): 返回整数(深度),bottom-up 合并
  • Day 60 (Count Good Nodes): 自顶向下传递当前路径最大值
  • 今天: 自顶向下传递双边界 (min, max),验证合法性

🐍 完整解法 + 追踪 / Solution with Trace

from typing import Optional

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def isValidBST(root: Optional[TreeNode]) -> bool:
    def validate(node, min_val, max_val):
        # Base case: empty node is valid
        if not node:
            return True
        
        # Current node must be strictly within (min_val, max_val)
        if not (min_val < node.val < max_val):
            return False
        
        # Recurse: left subtree bounded above by node.val
        #          right subtree bounded below by node.val
        return (validate(node.left, min_val, node.val) and
                validate(node.right, node.val, max_val))
    
    # Start with infinite bounds
    return validate(root, float('-inf'), float('inf'))

# Trace for BST: [5,1,4,null,null,3,6]  → Invalid
#        5           validate(5, -inf, +inf)
#       / \            5 in (-inf, +inf) ✅
#      1   4           validate(1, -inf, 5) → 1 in (-inf,5) ✅
#         / \          validate(4, 5, +inf) → 4 NOT in (5,+inf) ❌
#        3   6       → return False ✅ (correctly invalid)

# Trace for valid BST: [2,1,3]
#        2           validate(2, -inf, +inf) → ✅
#       / \          validate(1, -inf, 2) → 1 in (-inf,2) ✅
#      1   3         validate(3, 2, +inf) → 3 in (2,+inf) ✅
#                  → return True ✅

复杂度 / Complexity:

  • 时间 Time: O(n) — 每个节点访问一次
  • 空间 Space: O(h) — 递归栈,h=树高;平衡树 O(log n),最坏 O(n)

❌ 常见错误 / Common Mistake

# WRONG: 只比较父子节点,忽略全局范围
# This fails for [5, 4, 6, null, null, 3, 7]
def isValidBST_WRONG(root):
    def check(node):
        if not node: return True
        if node.left and node.left.val >= node.val: return False
        if node.right and node.right.val <= node.val: return False
        return check(node.left) and check(node.right)
    # ❌ node 6's left child 3 < 5 (root), violates BST!
    # But this code says it's valid because 3 < 6 locally

# CORRECT: 传递边界 / Pass bounds
def isValidBST_CORRECT(root):
    def validate(node, lo, hi):
        if not node: return True
        if not (lo < node.val < hi): return False
        return validate(node.left, lo, node.val) and \
               validate(node.right, node.val, hi)
    return validate(root, float('-inf'), float('inf'))

举一反三 / Pattern Connections

这道题在 Trees 板块的位置:

  • #235 LCA of BST (Day 62): 利用 BST 性质找分叉点 → 方向类似(利用范围导航)
  • #230 Kth Smallest in BST (Day 68): 利用中序遍历天然有序
  • #105 Construct BST from Preorder/Inorder (Day 70): 用范围界定子树

通用洞察: BST 问题 = 普通树 DFS + 利用 BST 有序性(范围/中序)


📚 参考资料 / References

  1. LeetCode #98 Discussion
  2. NeetCode BST Explanation
  3. BST Properties — CS Visualizations

🧒 ELI5

验证 BST 就像检查每层楼的门牌号:不只是"这层比下面高",而是每个房间的号码必须在整栋楼允许的范围内。

Validating a BST is like checking room numbers floor by floor: it's not just "higher than below" — every room must be within its globally allowed range.

🗣️ 软技能 / Soft Skills — Day 67

题目 / Question: Tell me about a time you had to balance individual contribution with team enablement

类型 / Category: Leadership (Staff Level)

预计阅读 / Read time: ~2 min


🗣️ 软技能 / Soft Skills

"讲一次你需要在个人贡献和团队赋能之间找平衡的经历。"

"Tell me about a time you had to balance individual contribution with team enablement."


🎯 为什么这道题很重要 / Why This Matters

这是 Staff+ 工程师的核心困境:你的代码产出在下降,但你的影响力在上升。 面试官想知道:你是否理解 Staff 工程师的价值来自放大团队,而不只是个人产出。

This is the core Staff+ dilemma: your code output decreases, but your impact multiplies. Interviewers want to know: do you understand that Staff value comes from multiplying the team, not just your own output?


⭐ STAR 结构 / STAR Framework

Situation 背景:

"我们有一个关键的性能重构项目,周期 6 周,我是最熟悉这块代码的人。同时团队有 2 名新加入的高级工程师需要 onboarding。"
"We had a critical 6-week performance refactor. I was the most familiar with the codebase. Meanwhile, 2 newly joined senior engineers needed onboarding."

Task 任务:

"我需要决定:自己全力冲刺完成项目,还是花时间带新人——这可能让项目延期 1-2 周。"
"I had to decide: sprint solo to hit the deadline, or invest in onboarding — which might slip the timeline by 1-2 weeks."

Action 行动:

"我做了一个混合策略:把项目拆成两层。第一层是核心关键路径(约 40% 工作),我独立完成;第二层是模块化子任务,我设计了完整的技术文档和测试框架,让两位新工程师上手。我每天 30 分钟代码 review + 答疑,而不是 pair programming 全天。"
"I used a hybrid approach: split the project into two layers. Layer 1 (critical path, ~40%) I owned solo. Layer 2 I documented thoroughly with test scaffolding, letting the two engineers take it on. Daily 30-min review sessions, not full-day pairing."

Result 结果:

"项目整体只晚了 4 天,但两位工程师在第 3 周就能独立推进了。三个月后他们领导了下一个类似项目,我根本不用参与。"
"We shipped only 4 days late. By week 3, both engineers were self-sufficient. Three months later they led a similar project without me."

❌ Bad vs ✅ Good

❌ 错误答案✅ 优秀答案
焦点"我加班自己搞定了,没有delay"明确说出了取舍和选择依据
结果只说完成了任务说出了长期杠杆效应(团队变强)
视角以自己为中心以团队+公司目标为中心

🌟 Senior/Staff 进阶技巧 / Level-Up Tips

你可以主动加分的点:

  1. 量化杠杆效应:"我花了 20 小时 onboarding,换来了团队多 400 小时的未来产能"
  2. 说出框架:"我的原则是:如果这件事只有我能做,我做;如果可以教别人,我优先教"
  3. 主动提到代价:"是的,我们稍微 slip 了,我和 EM 对齐了这个决策,他们认可"

关键词到加入答案里 / Power phrases:

  • "force multiplier" — 放大器
  • "bus factor" — 单点风险
  • "sustainable pace" — 可持续节奏

💡 关键要点 / Key Takeaways

  1. Staff 工程师的价值 = 个人产出 × 团队倍数,不只是自己写多少代码
  2. 平衡不是 50/50,而是动态调整,根据项目紧迫度和人员成熟度
  3. 面试时说出你如何决策,比结果更重要

📚 参考资料 / References

  1. Will Larson — Staff Engineer: Leadership beyond the management track
  2. The Engineer/Manager Pendulum — Charity Majors
  3. Being Glue — Tanya Reilly

🧒 ELI5

就像篮球明星选择传球还是自己投:高手知道什么时候自己投(赢关键球),什么时候传给队友(培养团队,赢整个赛季)。

Like a basketball star choosing to shoot vs. pass: great players know when to take the shot themselves (win the crucial moment) and when to pass (develop the team, win the season).

🤖 AI 动态 / AI News — Day 67

模式 / Mode: NEWS

日期 / Date: 2026-06-16

预计阅读 / Read time: ~2 min


🤖 AI 动态 / AI News Roundup

本周 AI 圈发生了什么?/ What happened in AI this week?


📰 Story 1: SpaceX Colossus 延迟问题被曝光,被迫租给 Anthropic 和 Google

发生了什么?/ What happened?

据 Bloomberg 报道,SpaceX 原计划在 Memphis 的 Colossus 1 数据中心用三个园区联合训练 Grok,但因为站点间距超过 10 英里、叠加老旧网络基础设施,导致严重的网络延迟问题。无法自用后,SpaceX 转而将算力出租给 Anthropic(据报道 $15B/年)和 Google(据报道 $920M/月)。

According to Bloomberg, SpaceX planned to train Grok across three data center campuses at Colossus 1, but hit latency issues when connecting sites over 10 miles apart, compounded by aging network infrastructure. Unable to use it themselves, SpaceX reportedly rented capacity to Anthropic and Google.

🔗 来源 Source: Bloomberg / The Verge

为什么重要?/ Why it matters:

分布式训练对网络延迟极度敏感——哪怕几毫秒的 inter-node 延迟都会拖垮整体训练效率。这也说明"拥有算力"和"有效使用算力"之间存在巨大的工程鸿沟。

Distributed training is extremely latency-sensitive — even milliseconds of inter-node delay can tank training efficiency. It shows a massive engineering gap between "owning compute" and "effectively using compute."


📰 Story 2: 政府叫停 Anthropic 最新最强模型

发生了什么?/ What happened?

The Verge 援引知情人士透露,美国政府叫停了 Anthropic 最新、最强大的模型发布,理由是认为该模型"功能过于强大"。Anthropic 和其他 AI 支持者据报道花了整个周末试图解释该模型并不像政府担心的那样危险。

The Verge cited sources saying the US government blocked Anthropic's newest, most powerful model from release, citing concerns it was "too powerful." Anthropic and AI advocates reportedly spent the weekend explaining that the model — referred to as "Fable 5" in some reporting — wasn't as dangerous as feared.

🔗 来源 Source: The Verge

为什么重要?/ Why it matters:

AI 监管实际落地来了。政府开始主动干预模型发布,而不只是讨论框架。这将影响 AI lab 的发布节奏和能力展示方式。

AI regulation is landing in real time. Governments are actively intervening in model releases, not just discussing frameworks. This will reshape how AI labs release and communicate capabilities.


📰 Story 3: Elon Musk 再次在对 OpenAI 诉讼中败诉

发生了什么?/ What happened?

Elon Musk 在对 OpenAI 的诉讼中再次败诉。这是他试图通过法律手段阻止 OpenAI 从非营利组织转型为营利公司的系列诉讼之一,但法院再次驳回了他的请求。

Elon Musk lost his legal battle against OpenAI again — another failed attempt to legally block OpenAI's transition from a nonprofit to a for-profit structure.

🔗 来源 Source: The Verge

为什么重要?/ Why it matters:

OpenAI 的公司结构转型基本已无法律障碍,意味着其融资能力和商业化路径将更清晰。同时也折射出 AI 行业的治理争议远未结束。

OpenAI's corporate restructuring is now largely legally unobstructed, clearing the way for larger fundraising and clearer commercial paths. The governance debate in AI, however, is far from over.


💡 本周思考 / This Week's Takeaway

算力 ≠ AI 能力。 SpaceX 有世界顶级的硬件,却因为基础网络工程问题无法自用。AI 的瓶颈往往不在参数量,而在系统工程。

Compute ≠ AI capability. SpaceX had world-class hardware, but basic networking engineering issues blocked self-use. AI bottlenecks are often not parameter counts — they're systems engineering.


📚 参考资料 / References

  1. SpaceX Colossus latency issues — Bloomberg via The Verge
  2. Government blocks Anthropic model — The Verge
  3. Musk loses OpenAI lawsuit — The Verge (Jun 15)

🧒 ELI5

就算你有世界上最强的厨房设备,厨师们如果没法互相沟通配合,做出来的菜还是一团糟。AI 训练也一样——硬件再好,网络不行就白搭。

Even with the world's best kitchen equipment, if the chefs can't communicate, the meal is a mess. Same with AI training — great hardware means nothing if the network is broken.