← 2026-05-28 📂 All Days 2026-05-30 →

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

多区域 Active-Active 系统设计 / Design a Multi-Region Active-Active System


🌍 真实场景 / Real-World Scenario

想象你在 Stripe 负责支付基础设施。黑色星期五来临,单个数据中心每秒处理 10 万笔交易。一场区域性断电会让全球业务瘫痪、损失数亿美元。你的任务:设计一个多区域 active-active 系统,让任何一个区域挂掉都不影响全局。

Imagine you're at Stripe running payment infrastructure. Black Friday arrives, your single data center processes 100K TPS. One regional outage costs hundreds of millions. Your job: design a multi-region active-active system where any single region can fail without global impact.


📐 架构图 / ASCII Architecture

┌─────────────────────────────────────────────┐ │ Global Load Balancer (Anycast IP) │ │ GeoDNS / AWS Global Accelerator │ └──────────┬──────────────┬────────────────────┘ │ │ ┌─────────▼──────┐ ┌───▼─────────────┐ │ Region: US-W │ │ Region: EU-W │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ │ API Layer │ │ │ │ API Layer │ │ │ │ (AZ × 3) │ │ │ │ (AZ × 3) │ │ │ └──────┬──────┘ │ │ └──────┬──────┘ │ │ ┌──────▼──────┐ │ │ ┌──────▼──────┐ │ │ │ DB Primary │ │ │ │ DB Primary │ │ │ │ (writes) │◄├──┼─┤► (writes) │ │ │ │ + Replicas │ │ │ │ + Replicas │ │ │ └─────────────┘ │ │ └─────────────┘ │ │ ┌─────────────┐ │ │ ┌─────────────┐ │ │ │ Cache │ │ │ │ Cache │ │ │ │ (Redis) │ │ │ │ (Redis) │ │ │ └─────────────┘ │ │ └─────────────┘ │ └────────┬────────┘ └────────┬─────────┘ │ │ ┌────────▼────────────────────▼─────────┐ │ Async Replication / CDC (Kafka) │ │ Global Control Plane (consensus) │ └────────────────────────────────────────┘

⚖️ 关键权衡 / Key Tradeoffs

为什么要 Active-Active 而不是 Active-Passive?

Why Active-Active instead of Active-Passive?

维度Active-PassiveActive-Active
RTO分钟级(需要故障转移)秒级(流量即时切换)
读吞吐仅主区域全球就近读
写冲突无需要处理!
复杂度低高

写冲突解决 / Conflict Resolution:

  1. 最后写入胜(LWW) — 简单但可能丢数据,适合 metrics/logging
  2. 向量时钟(Vector Clocks) — 检测并发写,应用层解决,适合文档
  3. CRDT(Conflict-free Replicated Data Types) — 自动合并,适合计数器、集合
  4. 事务路由(Transaction Routing) — 按 user_id 哈希路由到固定区域写,消除冲突(推荐用于支付)

数据分区策略 / Data Partition Strategy:

  • 用户就近原则:欧洲用户数据写 EU 区域,通过 GDPR 合规
  • 全局实体(如商品库存):需要真正的分布式事务,代价极高
  • 本地实体(用户会话、订单):路由到固定区域,避免冲突

🎯 三大核心挑战 / Three Core Challenges

1. 复制延迟 / Replication Lag

  • 跨大陆延迟 ~100-150ms,数据不一致窗口真实存在
  • 方案:读自己的写(read-your-writes)—— 写完后短暂路由到同一区域读

2. 脑裂 / Split Brain

  • 网络分区时两个区域都认为自己是主
  • 方案:引入 Global Control Plane(用 Raft 共识),检测分区后降级为 active-passive

3. 故障检测 / Failure Detection

  • 不要依赖单点健康检查,用 Route 53 Health Checks + 跨区域 ping
  • 自动 failover 配合熔断器,避免雪崩

🚫 别踩这个坑 / Common Mistakes

  1. 坑:假设网络总是通的 — 设计时必须考虑分区(P in CAP)
  2. 坑:所有数据都做 active-active — 区分全局实体 vs 局部实体,局部实体不需要跨区同步
  3. 坑:忽视时钟偏移 — 分布式系统里不要用本地时间做排序,用混合逻辑时钟(HLC)或 CockroachDB 的 TrueTime
  4. 坑:过度工程 — 大多数公司在到达 active-active 需要之前就 IPO 了;先做 active-passive + 快速 failover

📚 References


🧒 ELI5

想象一家全球连锁餐厅。Active-Passive 就像只有北京总店能接单,其他城市的店只是备份。Active-Active 就像每个城市都能独立接单、做菜,但偶尔菜单更新要同步,如果北京和上海同时修改了同一道菜的价格,得有个规则决定谁的算数。

Think of a global restaurant chain. Active-Passive: only HQ takes orders, others are on standby. Active-Active: every city takes orders independently, but when two cities update the same menu item simultaneously, you need a rule for whose version wins.

💻 算法 / Algorithms — Day 46

#226 Invert Binary Tree (Easy) — Trees


🧩 新模式 / New Pattern: 树遍历模式 (Tree Traversal)

📍 This block: 15 problems (Easy → Hard)

什么时候用 / When to use: 二叉树遍历、路径问题、验证 BST、层序遍历

识别信号 / Signals: binary tree, BST, path sum, level order, depth, validate

通用模版 / Template:

def dfs(node):
    if not node:
        return BASE_CASE      # e.g. 0, None, True, []
    left = dfs(node.left)
    right = dfs(node.right)
    return COMBINE(node.val, left, right)

核心洞察 / Key Insight:

几乎所有树问题都是 DFS 递归 — 关键是定义好返回值语义:我要从子树得到什么?

Almost all tree problems are DFS recursion — the key is defining the return value semantics: what do I need back from each subtree?


🔗 LeetCode #226 🟢 Easy

📹 NeetCode 视频


🌍 真实类比 / Real-World Analogy

想象你有一棵组织架构图,需要把左右子公司互换 —— 每个节点都要把左右孩子对调,然后递归处理。就像镜像翻转一面镜子:每个小镜子都要翻,大镜子才完整翻好。

Imagine an org chart where you need to mirror left and right subsidiaries at every level. Like reflecting in a mirror: every node must swap its children for the whole tree to be inverted.


🗺️ 映射到模板 / Mapping to Template

BASE_CASE = None (空节点不需要处理) left = dfs(node.left) → 反转左子树,返回反转后的根 right = dfs(node.right) → 反转右子树,返回反转后的根 COMBINE = swap(left, right) → 把返回结果互换赋给 node

💻 Python 解法 / Solution

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 invertTree(root: Optional[TreeNode]) -> Optional[TreeNode]:
    # Base case: empty node — nothing to invert
    if not root:
        return None
    
    # Post-order: recurse first, then process current node
    left  = invertTree(root.left)
    right = invertTree(root.right)
    
    # COMBINE: swap left and right children
    root.left  = right
    root.right = left
    
    return root

# Trace example:
#      4                4
#    /   \    →       /   \
#   2     7         7     2
#  / \ / \         / \   / \
# 1  3 6  9       9  6  3  1
#
# invertTree(4):
#   invertTree(2) → returns root of [2, right=1, left=3]
#   invertTree(7) → returns root of [7, right=6, left=9]
#   swap: 4.left = [7...], 4.right = [2...]
#   return 4

Time Complexity: O(n) — visit every node once

Space Complexity: O(h) — recursion stack, h = height (O(log n) balanced, O(n) skewed)


🔄 举一反三 / Block Connections

这个模板后续会用于:

  • #104 最大深度 — COMBINE = 1 + max(left, right),返回深度数字
  • #543 直径 — COMBINE 更新全局最大值,返回单边最长路径
  • #110 平衡树 — COMBINE 检查 abs(left - right) <= 1,返回高度或 -1(invalid)
  • 规律:越是 Easy,COMBINE 越简单;Hard 题的 COMBINE 会更新全局变量

The template evolution:

  • #104: return depth (int), COMBINE = 1 + max(l, r)
  • #543: track global max, return single-arm length
  • #124 Hard: track global max path sum, return best single-arm sum

📚 References


🧒 ELI5

有一棵圣诞树,每个树枝都有左小树枝和右小树枝。反转就是把每个树枝的左右小树枝互换。先处理最小的树枝(叶子),再处理大的,最后换根。

You have a Christmas tree. At every branch, swap the left and right sub-branches. Start with the tiniest branches (leaves), work your way up, and finally swap the two main branches at the top.

🗣️ 软技能 / Soft Skills — Day 45

Leadership: 如何给绩效不佳的高级工程师反馈 / Giving Feedback to an Underperforming Senior Engineer


🎯 为什么这道题难 / Why This Is Hard

这是 Staff/Principal 面试中最高频的领导力题之一。难点不在技术,在于:

  1. 高级工程师通常自尊心强,直接批评容易激发防御反应
  2. 你可能没有正式汇报关系(lateral feedback)
  3. 做不好影响团队士气,做过头可能伤害关系

This is one of the most common Staff/Principal leadership questions. The difficulty: senior engineers often have strong egos, lack of formal authority complicates delivery, and getting it wrong damages team morale or the relationship.


📋 STAR 框架 / STAR Breakdown

Situation(背景): 具体化场景 — 比如,一位 Senior SWE 连续两个 sprint 没有完成承诺的 deliverable,且没有主动沟通

Task(任务): 作为 Tech Lead 或同级,你需要在正式绩效流程之前介入,给出有效反馈

Action(行动):

  1. 先私下了解背景 — 找个 1:1,先问"最近工作上有什么卡点?" 而不是直接指出问题
  2. 用事实而非评判 — "我注意到过去两周的 PR review 平均需要 4 天,团队的 velocity 受到了影响" vs "你太慢了"
  3. 用 SBI 模型 — Situation / Behavior / Impact
  4. 给予主动权 — "你觉得是什么原因?你需要什么支持?"
  5. 明确期望和时间线 — "接下来 2 周,我们对齐一个目标:每天至少完成 2 个 review"
  6. 后续跟进 — 不是 one-shot,而是持续观察和支持

Result(结果): 描述具体改善,或说明升级到 manager 的决定及依据


❌ 坏回答 vs ✅ 好回答

❌ Bad:

"我直接告诉他代码太烂了,这不符合我们的标准。"

问题:不尊重、无事实、无改善路径。

❌ Also bad:

"我把问题报给了经理,让他去处理。"

问题:逃避责任,失去直接反馈的机会。

✅ Good:

"我先在 1:1 里了解是否有我不知道的因素 — 比如他在 on-call 轮班期间承担了额外负担。然后用具体数据描述影响,问他的想法。我们一起制定了一个两周的改善计划,我每周 check in 一次。三周后,PR review 时间从 4 天降到了 1 天。"

🏆 Senior/Staff 加分项 / Senior/Staff Tips

  • 分离问题类型:是能力问题(skill gap)、动力问题(motivation)还是环境问题(blocked by others)?解法完全不同
  • 文档化:如果进入正式绩效流程,需要有记录。私下反馈也要发一封 follow-up email 确认讨论内容
  • 知道何时升级:如果 2-3 次反馈后没有改善,主动告知 manager,而不是一直自己扛
  • Psychological safety 优先:创造安全环境,对方才会说出真实卡点(个人问题、burnout 等)

💡 关键要点 / Key Takeaways

  1. 私下 → 问因 → 用事实 → 用 SBI → 给主动权 → 明确目标 → 持续跟进
  2. 反馈是礼物,但包装方式决定是否被接受
  3. Staff 工程师的职责包括提升周围人的能力,而不只是自己写好代码

📚 References


🧒 ELI5

就像告诉朋友他踢球时总是把球传错方向:不是说"你踢球太烂了",而是"刚才第 3 分钟那次传球,我站在你右边没有防守,但球传给了左边有人防守的队友,我们因此失去了一次进攻机会。下次可以先看看我的位置吗?"

Like telling a friend they keep making the wrong pass: not "you're bad at soccer," but "in minute 3, I was open on the right with no defender, but you passed left into coverage, and we lost the ball. Next time, check my position first?"

🤖 AI — Day 54

合成数据 / Synthetic Data — Training on AI-Generated Data


🤔 什么是合成数据 / What Is Synthetic Data?

合成数据(Synthetic Data)是指由算法或 AI 模型生成的训练数据,而非从真实世界收集。可以是文本、图像、代码、对话、标签等任何形式。

近年来,合成数据从"不得已的替代品"变成了顶尖模型的核心训练策略:OpenAI、Google、Meta 均大量使用合成数据训练模型。

Synthetic data is AI/algorithmically-generated training data, not collected from the real world. It's become a core training strategy — not a workaround — for top models.


⚙️ 它是怎么工作的 / How It Works

三种主要方式 / Three Main Approaches:

1. 大模型蒸馏(Model Distillation)

用更强的大模型(Teacher)生成高质量输出,用于训练小模型(Student):

GPT-4 generates 100K high-quality math solutions → Fine-tune Llama-3-8B on these solutions → Small model learns teacher's reasoning style

2. 自我蒸馏(Self-Improvement / Self-Play)

模型生成输出 → 用另一个模型或规则打分 → 用高分样本继续训练:
LLM generates answer → Verifier checks correctness (math: check final answer) → Keep correct ones, discard wrong ones → Retrain on curated correct solutions

这正是 OpenAI o1/o3 背后的关键技术之一。

3. 数据增强(Data Augmentation)

对现有数据做变换生成更多:

# Text augmentation example
original = "The server crashed at 3am"
augmented = [
    "At 3am, the server went down",          # paraphrase
    "服务器在凌晨3点崩溃了",                  # translation
    "The [COMPONENT] crashed at [TIME]",      # template
]

💡 为什么有效 / Why It Works

数据飞轮 / Data Flywheel:

  • 真实数据有噪声、标注贵、分布不均
  • 合成数据可以精确控制难度、分布、格式
  • 特别适合:数学推理、代码、指令遵循(有客观 ground truth 可验证)

关键前提 / Key Prerequisite:

合成数据需要验证器(Verifier) —— 否则无法知道生成的数据是否正确。

  • 数学:直接检验答案
  • 代码:跑测试用例
  • 通用问答:难以自动验证 → 效果打折

Synthetic data works best where you have an automatic verifier — math answers, code tests. Open-ended QA is hard to verify automatically.


⚠️ 陷阱 / The Pitfalls

模型崩溃(Model Collapse):

如果模型反复在自己生成的数据上训练,会逐渐失去多样性,输出越来越同质化。就像复印机不断复印:每一代都比上一代更模糊。

研究表明,哪怕加入少量真实数据,也能显著缓解模型崩溃。

Gen 0: diverse real data Gen 1: synthetic from Gen 0 → slightly less diverse Gen 2: synthetic from Gen 1 → much less diverse Gen N: collapses to modal output

其他风险 / Other Risks:

  • 合成数据放大偏见(Teacher 模型的偏见 × 规模)
  • 法律问题(用 GPT 生成的数据训练竞争模型,OpenAI ToS 明确禁止)

🐍 可运行示例 / Runnable Example

# pip install openai
# Simple synthetic data generation pipeline

import json

def generate_qa_pair(topic: str, client) -> dict:
    """Generate one synthetic Q&A pair for a given topic."""
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{
            "role": "user",
            "content": f"""Generate a challenging technical Q&A about: {topic}
            
            Return JSON with keys: question, answer, difficulty (1-5)
            Keep answer under 100 words."""
        }],
        response_format={"type": "json_object"}
    )
    return json.loads(response.choices[0].message.content)

# Usage (requires OPENAI_API_KEY):
# from openai import OpenAI
# client = OpenAI()
# pair = generate_qa_pair("Python GIL", client)
# print(pair)
# → {"question": "Why does threading not help CPU-bound tasks?",
#    "answer": "The GIL...", "difficulty": 3}

📚 References


🧒 ELI5

想象你要学钢琴,但没有老师。你的方法是:用 AI 生成 10 万个"完美演奏示例",然后自己练习模仿。如果这些例子都是真正的好例子,你会进步很快。但如果你只练自己生成的例子(自己模仿自己),就像照镜子照了 100 代,最后图像全是模糊的。

Imagine learning piano with no teacher: generate 100K "perfect performance examples" with AI and imitate them. It works if the examples are genuinely good. But if you only practice by imitating your own playing (generation after generation), it's like photocopying a photocopy 100 times — quality degrades.