← 2026-06-16 📂 All Days 2026-06-18 →

🏗️ 系统设计 / System Design — 分布式追踪系统 (Jaeger/Zipkin)

Day 68 · Expert Phase · ~3 min read

场景 / The Scenario

想象你在 Uber 工程团队:一个打车请求失败了,用户报告"无法匹配司机"。这个请求经过了 **API Gateway → Ride Service → Matching Service → Driver Service → Notification Service**,跨越 5 个微服务、3 个数据库、2 个消息队列。你怎么找到哪一步慢了?

You're on the Uber engineering team: a ride request failed. It touched 5 microservices, 3 databases, 2 queues. How do you find the bottleneck?

答案 / Answer: 分布式追踪系统。Distributed tracing.


架构图 / Architecture

┌─────────────────────────────────────────┐ │ Client App / API Gateway │ │ generates TraceID: abc123, SpanID: 1 │ └──────────────────┬──────────────────────┘ │ HTTP Header: X-Trace-ID: abc123 ┌──────────────────────────┼──────────────────────────┐ ▼ ▼ ▼ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ Ride Service │ │ Auth Service│ │ Maps Service │ │ SpanID: 2 │ │ SpanID: 3 │ │ SpanID: 4 │ │ parent: 1 │ │ parent: 1 │ │ parent: 1 │ └──────┬───────┘ └──────────────┘ └──────────────┘ │ ┌──────▼───────┐ │ DB Query │ │ SpanID: 5 │ │ parent: 2 │ │ latency: 450ms ⚠️│ └──────────────┘ Each service sends span data to: ┌─────────────────────────────────────────┐ │ Collector (Jaeger Agent) │ │ Receives spans via UDP (fire-and-forget)│ └──────────────────┬──────────────────────┘ │ ┌──────────▼──────────┐ │ Storage Backend │ │ Cassandra / ES / │ │ Badger (local dev) │ └──────────┬──────────┘ │ ┌──────────▼──────────┐ │ Query Service │ ◄── Jaeger UI / Grafana Tempo │ TraceID lookup │ │ Dependency graph │ └─────────────────────┘

核心概念 / Core Concepts

Span 是什么?

一个 span = 一个操作单元,包含:

  • trace_id: 整条请求链路的唯一 ID
  • span_id: 本次操作的 ID
  • parent_span_id: 谁调用了我
  • operation_name, start_time, duration
  • tags (key-value), logs (events), status

A span = one unit of work. A trace = a tree of spans sharing the same trace_id.

Context Propagation(上下文传播)

TraceID 需要在每次跨服务调用时传递:

  • HTTP: X-B3-TraceId, X-B3-SpanId headers (Zipkin B3 format)
  • gRPC: Metadata headers
  • Async/Queue: Message headers (Kafka, RabbitMQ)
  • OpenTelemetry: W3C traceparent header (now the standard)

采样策略 / Sampling Strategies

为什么需要采样? 100% 采样会产生巨量数据,影响性能。

Why sample? 100% tracing = too much data, too much overhead.

策略说明适用场景
Head-based在入口处决定采样(随机 1%)低流量,简单
Tail-based请求完成后,根据结果决定(保留错误/慢请求)生产首选
Adaptive动态调整采样率(Jaeger 默认)高流量系统

最佳实践: Tail-based sampling — 总是保留 error traces 和 P99 以上的慢 trace。


关键权衡 / Key Tradeoffs

存储选择

  • Cassandra: 高写入吞吐,水平扩展佳 → Jaeger 生产首选
  • Elasticsearch: 全文搜索,适合日志 + 追踪融合
  • ClickHouse: Grafana Tempo 后端,列存储,超快聚合

Push vs Pull

  • Jaeger: 服务推送 spans 到 Agent(UDP,低延迟,不阻塞)
  • OpenTelemetry Collector: 可配置 pipeline,支持 fan-out 到多个后端

与日志/指标的关系 (三大支柱)

Logs → What happened (事件记录) Metrics → How much / how fast (聚合数字) Traces → Why it happened (因果链路)

别踩这个坑 / Common Mistakes

❌ 同步发送 spans — 会增加服务延迟

✅ 异步 + UDP — fire-and-forget,span 丢失可接受(比业务延迟更重要)

❌ 100% 采样上生产 — 数据量是请求量的 10-100x

✅ 1% 随机 + 100% 错误/慢请求

❌ 只追踪 HTTP,忘了 DB/Queue

✅ 插桩所有 I/O:DB queries, external HTTP calls, queue publishes

❌ TraceID 不传给异步 worker

✅ 把 TraceID 放进消息体/headers,让下游能关联


📚 References


🧒 ELI5

你和朋友去迷宫,每个人都有一根毛线球,进每个房间都撕一段贴上自己名字。如果有人迷路了,顺着毛线就能找回来,还能看出谁进了哪些房间、用了多长时间。

Imagine a maze where everyone carries a ball of yarn and tears off a piece in each room with their name on it. If someone gets lost, you follow the yarn trail — and you can see exactly who went where and how long they spent there. Distributed tracing is that yarn for microservice requests.

💻 算法 / Algorithms — #230 Kth Smallest Element in a BST (Medium)

Day 68 · Expert Phase · ~4 min read
🧩 树遍历模式 (12/15) — 在第 Day 57 的模板基础上延伸

🧩 树遍历模式 (12/15) — 从 Day 57 模板延伸

之前的模板:后序 DFS(左 → 右 → 当前)。 今天的变体:**中序 DFS(左 → 当前 → 右)** — BST 的中序遍历天然有序!
Previous pattern: post-order DFS (left → right → current).

Today's twist: in-order DFS — because a BST's in-order traversal yields sorted values automatically.

模板变体对比: Post-order: left, right, THEN process node → aggregation (depth, path sum) In-order: left, THEN process node, right → BST sorted traversal Pre-order: THEN process node, left, right → serialization, path recording

题目 / Problem

🔗 LeetCode #230 🟡 Medium

📹 NeetCode Video

真实类比 / Real-world analogy:

你有一个员工薪资 BST(左小右大)。老板问:"第 3 低的薪资是多少?" — 你不用排序整个数组,只需按序遍历到第 k 个就停下。

You have a salary BST (left < right). The boss asks: "What's the 3rd lowest salary?" You don't need to sort everything — just traverse in order and stop at the k-th element.

问题: 给一棵 BST,找第 k 小的元素(k 从 1 开始)。

Given a BST, return the k-th smallest value (1-indexed).

Input: root = [3,1,4,null,2], k = 1

      3
     / \
    1   4
     \
      2

In-order: 1, 2, 3, 4
Output: 1

解题思路 / Approach — 映射到中序模板

**BST 的关键性质:** 中序遍历(左→根→右)结果是**升序排列**。

Key BST property: In-order traversal yields values in ascending order.

所以第 k 小 = 中序遍历的第 k 个节点。

方法一: 迭代中序(推荐,面试首选)

Iterative in-order (preferred for interviews — early termination):

def kthSmallest(root, k: int) -> int:
    stack = []
    current = root
    count = 0

    while current or stack:
        # Go as far left as possible
        while current:
            stack.append(current)
            current = current.left

        # Process node (this is "in-order" moment)
        current = stack.pop()
        count += 1
        if count == k:
            return current.val  # Early exit!

        # Move to right subtree
        current = current.right

执行追踪 / Trace (root=[3,1,4,null,2], k=1):

Step 1: Push 3, push 1, push null → stack=[3,1], current=None Step 2: Pop 1, count=1, k=1 → RETURN 1 ✓

方法二: 递归(清晰,但无法早退)

Recursive (cleaner, but can't early-terminate):

def kthSmallest(root, k: int) -> int:
    result = []

    def inorder(node):
        if not node or len(result) == k:
            return
        inorder(node.left)         # left first
        result.append(node.val)    # process current
        inorder(node.right)        # then right

    inorder(root)
    return result[k - 1]

复杂度 / Complexity

TimeSpace
IterativeO(H + k) — H = tree heightO(H) stack
RecursiveO(H + k)O(H) call stack

H = O(log n) for balanced, O(n) for skewed.

为什么是 O(H + k)? 先走 H 步到最左,再数 k 步。


Follow-up (面试加分项!)

"如果 BST 频繁插入/删除,查询 k-th 会很慢。怎么优化?"
"If the BST is modified frequently, how do you optimize repeated k-th queries?"

解法: 在每个节点存 left_count(左子树节点数),可以 O(log n) 查询:

Store left_count at each node → O(log n) per query:

# Node stores: val, left, right, left_count
# If k <= node.left_count: go left
# If k == left_count + 1: current is answer
# Else: k -= (left_count + 1), go right

举一反三 / Pattern Connections

在同一个树遍历模式块中 (In the same Trees pattern block):

  • #98 Validate BST (Day 67): 中序遍历验证递增 → 同样利用中序性质
  • #235 LCA of BST (Day 57): 利用 BST 的大小性质做方向决策
  • #105 Construct from Preorder+Inorder (下一题): 用中序恢复树结构

📚 References


🧒 ELI5

BST 就像一个自动整理好的书架,左边的书永远比右边便宜。找第 k 便宜的书,只要从最左边开始数,数到第 k 本停下来就行。

A BST is like a self-sorted bookshelf where left books always cost less than right ones. To find the k-th cheapest, just start from the leftmost book and count to k — no need to sort anything first.

🗣️ 软技能 / Soft Skills — 季度目标设定与沟通

Day 68 · Expert Phase · Staff Level · ~2 min read

题目 / Question

"How do you approach setting and communicating team goals each quarter?"


为什么这道题重要 / Why It Matters

Staff+ 工程师被期望**主动驱动目标对齐**,而不是等 PM 下发任务。面试官想看:你是否能把公司战略 → 团队目标 → 个人工作串联起来,并且能清晰地向上、向下、横向沟通。
At Staff+, you're expected to drive goal alignment proactively — not wait for PM to hand you a roadmap. Interviewers want to see how you cascade company strategy → team goals → individual work, and communicate it in all directions.

STAR 框架拆解 / STAR Breakdown

❌ 弱回答 (Weak)

"我们每季度开一次规划会,大家各自说说想做什么,然后 PM 整理成 OKR。"

问题:被动,无结构,无影响力体现。

✅ 强回答框架 (Strong)

Situation: 上季度团队有 7 个并行项目,没有清晰优先级,最后 3 个都没完成。

We had 7 parallel projects last quarter with no clear priority — 3 ended up incomplete.

Task: 我作为 tech lead,需要在下个季度建立一个目标框架,确保团队聚焦。

Action:

  1. 向上对齐 (Top-down): 参加产品 QBR,提炼出公司层面的 2-3 个核心押注
  2. 自下而上收集 (Bottom-up): 1:1 问每个工程师:"你觉得现在最大的技术债/机会是什么?"
  3. 目标草案: 写 3 个 OKR,每个 KR 都有可量化指标(不用"improve performance",用"P99 latency < 200ms")
  4. 对齐共识: 在 team meeting 上展示,允许 push back,明确 什么不做 同样重要
  5. 透明进度: 每两周 async 更新,红/黄/绿状态,不等月报

Result: 团队下季度完成了 4/4 目标,且每个人都知道自己的工作如何影响业务指标。


Senior vs Staff 的区别 / Seniority Differentiator

SeniorStaff
目标来源PM 给我 OKR我帮 PM 定 OKR
沟通范围团队内跨团队 + 向上
关注点我的 scope 能否完成整个 team 是否在做正确的事
说"不"能力偶尔系统性地保护团队专注力

关键要点 / Key Takeaways

  • ✅ 好的 OKR 必须有取舍 — 什么都是优先 = 什么都不是优先
  • ✅ "明确不做什么" 和 "明确做什么" 同样重要
  • ✅ 用可量化 KR,避免模糊动词(improve / enhance / explore)
  • ✅ 季度中期 check-in,不要等到结束才知道红灯

📚 References


🧒 ELI5

就像出发旅行前,你要先决定去哪里(目标),再约好大家怎么判断到了(可量化指标),还要说清楚不去哪里(取舍)。否则每个人都在开车,但方向不一样。

Like planning a road trip: first decide where you're going (goal), agree on how you'll know you've arrived (measurable KR), and say clearly where you're NOT going (trade-offs). Otherwise everyone's driving in different directions.

🤖 AI — 开源 vs 闭源 LLM:格局全览

Day 68 · Expert Phase · Industry · ~2 min read

格局概览 / The Landscape

2026 年,LLM 世界的核心张力:开源 vs 闭源。这不只是技术选择,更是商业模式、数据安全、能力上限的全面博弈。

In 2026, the core tension in the LLM world is open source vs. closed source — a competition spanning technical capability, business models, and data control.


主要玩家 / Key Players

🔒 闭源 / Closed Source

模型公司特点
GPT-4o / o3OpenAI多模态强,工具调用成熟
Claude 3.5 / Opus 4Anthropic长上下文,代码能力强,对齐严格
Gemini 2.5 ProGoogle集成 Google 生态,原生多模态
Grok 3xAI实时 X/Twitter 数据,推理特长

🔓 开源 / Open Source

模型来源特点
Llama 3.xMeta最广泛部署,社区生态最强
Mistral / MixtralMistral AI法国公司,MoE 架构,效率出众
Qwen 2.5Alibaba多语言(中文尤强),Apache 2.0
DeepSeek V3/R1DeepSeek训练成本极低,推理模型出众
Gemma 3Google小型高效,适合边缘部署

核心对比 / Core Tradeoffs

开源 Open Source 闭源 Closed Source ───────────────────── ───────────────────── 成本 Cost 自托管 = 硬件成本 按 token 计费,无前期成本 Self-host = infra cost Pay-per-token, no upfront 数据隐私 Privacy ✅ 数据不离本地 ⚠️ 数据发送给第三方 Data stays on-prem Data sent to vendor 定制化 Fine-tuning ✅ 完全可控,LoRA/QLoRA ⚠️ 有限 (OpenAI ft API) Full control Limited fine-tuning 性能上限 SOTA 通常滞后 6-12 个月 ✅ 通常领先 Usually lags 6-12 months Usually ahead 合规 Compliance ✅ 适合金融/医疗等高合规 需要 BAA/DPA 协议 Great for regulated Need contracts 运维负担 Ops ⚠️ 需要 GPU 集群 + MLOps ✅ 无需维护 GPU cluster + MLOps Zero ops burden

关键洞察 / Key Insights

为什么开源在快速追赶?

  1. Meta 的战略: 开源 Llama 削弱竞争对手的护城河(既然我不靠模型本身赚钱)
  2. 中国公司发力: DeepSeek、Qwen 以极低成本达到闭源级别性能,重塑了"需要多少算力"的预期
  3. 社区效应: Hugging Face 生态让微调、评测、部署成本急剧下降

为什么闭源仍有优势?

  1. 多模态先发: GPT-4o 的语音/视觉整合仍领先
  2. 工具生态: OpenAI 的函数调用、Code Interpreter 成熟度高
  3. 安全投入: Anthropic Constitutional AI,合规场景有保障

实践决策框架 / Practical Decision Framework

需要处理敏感数据?→ 开源(本地部署) Need sensitive data? → Open source (on-prem) 需要最强多步推理?→ 闭源 (o3, Claude Opus) Need best multi-step reasoning? → Closed source 预算有限,团队小?→ 闭源 API(无运维成本) Limited budget, small team? → Closed source API 需要深度定制行业模型?→ 开源(微调 Llama/Qwen) Need industry fine-tuning? → Open source 中文为主的应用?→ Qwen 2.5 / DeepSeek Chinese-primary app? → Qwen 2.5 / DeepSeek

可运行代码 / Runnable Code

# pip install transformers torch huggingface_hub
from transformers import pipeline

# 本地运行开源模型 / Run open source model locally
pipe = pipeline(
    "text-generation",
    model="Qwen/Qwen2.5-0.5B-Instruct",  # ~1GB, runs on CPU
    max_new_tokens=100,
    device=-1  # CPU
)

response = pipe("Explain the difference between open and closed source LLMs in 2 sentences.")
print(response[0]["generated_text"])

# 对比:调用 OpenAI API / Compare: calling OpenAI API
# pip install openai
# from openai import OpenAI
# client = OpenAI()
# r = client.chat.completions.create(model="gpt-4o-mini", messages=[{"role":"user","content":"..."}])

📚 References


🧒 ELI5

开源 LLM 就像公开菜谱的餐厅:你可以自己做,可以改配方,但要自己买锅碗瓢盆。闭源就像外卖:方便、即开即用,但厨房里发生什么你不知道,而且每次都要付钱。

Open source LLMs are like restaurants that share their recipes: you can cook yourself, modify the dish, but you need to buy your own kitchen. Closed source is like food delivery: convenient, ready to use, but you don't know what happens in the kitchen, and you pay every time.

Attention Heatmap

When the model processes it, it attends most strongly to animal.

Theanimaldidntcrossthestreetbecauseitwastootired
it →