← 2026-07-21 📂 All Days 2026-07-23 →

🏗️ 系统设计 / System Design — Day 97 (Synthesis)

Expert Phase · Synthesis Mode

缓存、队列与一致性:三角权衡深度拆解

想象你是 Meta/字节跳动的高级架构师,需要同时应对:

  • 10亿 DAU 的 Feed 系统
  • 秒杀/热点事件瞬间百倍流量
  • 跨数据中心的最终一致性

这不是单一设计题,而是真实系统中最难的三角权衡。


三角关系:缓存 × 消息队列 × 一致性

┌─────────────────────┐ │ Client (CDN) │ └──────────┬──────────┘ │ ┌──────────▼──────────┐ │ API Gateway / │ │ Load Balancer │ └──┬──────────────┬───┘ │ │ ┌──────────▼──┐ ┌───▼──────────┐ │ Cache Layer │ │ Queue Layer │ │ (Redis L1) │ │ (Kafka) │ └──────┬───────┘ └──────┬────────┘ │ │ ┌──────▼──────────────────────▼───────┐ │ DB Cluster (Primary/Replica) │ │ + CDC (Change Data Capture) │ └─────────────────────────────────────┘

为什么这样设计?核心权衡

1. 缓存策略选择

策略优势风险适用场景
Cache-Aside精确控制、缓存未命中可容忍缓存击穿、代码侵入读多写少(用户 profile)
Write-Through写入即更新,强一致写放大、延迟增加金融交易记录
Write-Behind高吞吐写入、DB 压力小数据可能丢失计数器、日志
Read-Through代码简洁冷启动慢ORM 场景

真实教训:Twitter 的热点用户(Obama, Elon)导致缓存被无效化后雪崩。解法:特殊缓存层 + 读穿策略,不走普通 invalidation。

2. 消息队列:解耦还是增加复杂度?

用队列(Kafka/SQS)当:

  • 下游系统处理速度不匹配(削峰填谷)
  • 需要 event sourcing / audit trail
  • 多个消费者需要同一事件

不用队列当:

  • 需要同步确认(支付成功页面)
  • 延迟要求 < 10ms(游戏同步)
  • 团队没有运维能力

3. 一致性模型选择

Strong → Sequential → Causal → Eventual ↑ ↑ 高延迟、高成本 低延迟、可扩展 Spanner/TiDB DynamoDB/Cassandra

真实 Meta 架构:TAO(The Associations and Objects) 系统用 Causal Consistency,不是 Strong。为什么?因为你看到帖子比朋友晚 100ms 完全可以接受,但写 4ms 的强一致代价太高。


综合设计:Feed 系统 + 热点事件

# 热点检测 + 动态缓存调整
class HotKeyDetector:
    def __init__(self, redis_client, threshold=1000):
        self.redis = redis_client
        self.threshold = threshold  # requests/sec

    def track_and_decide(self, key: str) -> str:
        count = self.redis.incr(f"hotkey:{key}")
        self.redis.expire(f"hotkey:{key}", 60)

        if count > self.threshold:
            # Hot key: replicate to local cache
            return "LOCAL_CACHE"
        return "REDIS_CACHE"

# Fan-out 策略动态切换
def get_fanout_strategy(user_follower_count: int) -> str:
    if user_follower_count < 1000:
        return "PUSH"    # 写扩散: 发布时推送到所有粉丝 timeline
    elif user_follower_count < 1_000_000:
        return "HYBRID"  # 混合:小 V push,大 V pull
    else:
        return "PULL"    # 读扩散: 读取时实时聚合(大 V 专用)

别踩这个坑

❌ 缓存穿透:查询不存在的 key,每次都打 DB。

✅ 解法:布隆过滤器(Bloom Filter)预检 + 缓存空值

❌ 缓存雪崩:大量 key 同时过期,DB 被打垮。

✅ 解法:TTL 加随机抖动(ttl = base_ttl + random(0, 300))

❌ 分布式锁滥用:每个操作都加锁,吞吐量下降 10x。

✅ 解法:只在 critical section 加锁;用 CAS(Compare-And-Swap)替代锁


📚 References

🧒 ELI5

就像超市:热门商品(缓存)放收银台旁边,不热门的才去仓库拿(数据库)。但如果所有商品同时清空,收银台就崩了——所以要分批补货,而且先检查仓库有没有货(布隆过滤器)再去找。

💻 算法 / Algorithms — Day 97

#131 Palindrome Partitioning · Medium · Backtracking

🧩 回溯模式 (7/9) — building on the template from Day 88 (Subsets)

今天是回溯 block 第 7 题。模板还是那个,但今天的变化是:剪枝条件变成了回文检测。


问题

🔗 LeetCode #131 🟡 Medium

📹 NeetCode Solution

给定字符串 s,将其分割为若干子串,使每个子串都是回文串。返回所有可能的分割方式。

Example:

Input: s = "aab"
Output: [["a","a","b"],["aa","b"]]

真实世界类比

想象你在切披萨,每一刀只能在"对称"的位置切——如果一段饼是回文的才允许那一刀。你要找出所有合法的切法。


模板映射

def backtrack(path, choices):
    if IS_COMPLETE(path):      # 分割到末尾
        result.append(path[:])
        return
    for choice in choices:     # 枚举每个切割点
        if IS_VALID(choice):   # 子串是回文?
            path.append(choice)
            backtrack(path, NEXT_CHOICES)
            path.pop()         # 撤销

今天的关键变化:

  • IS_COMPLETE = start == len(s) (遍历完整个字符串)
  • IS_VALID = is_palindrome(s[start:end]) ← 核心剪枝!
  • NEXT_CHOICES = range(start+1, len(s)+1) (下一个起点到末尾)

Python 解法 + Trace

def partition(s: str) -> list[list[str]]:
    result = []
    n = len(s)

    def is_palindrome(sub: str) -> bool:
        return sub == sub[::-1]

    def backtrack(start: int, path: list[str]):
        # IS_COMPLETE: 分割到字符串末尾
        if start == n:
            result.append(path[:])
            return

        for end in range(start + 1, n + 1):
            substring = s[start:end]
            # IS_VALID: 只有回文才继续递归
            if is_palindrome(substring):
                path.append(substring)
                backtrack(end, path)   # 递归,起点向后移
                path.pop()             # 撤销(回溯)

    backtrack(0, [])
    return result

# Trace for s = "aab"
# backtrack(0, [])
#   end=1: "a" ✅ → path=["a"]
#     end=2: "a" ✅ → path=["a","a"]
#       end=3: "b" ✅ → path=["a","a","b"] → COMPLETE ✅
#     end=3: "ab" ❌ palindrome? No → skip
#   end=2: "aa" ✅ → path=["aa"]
#     end=3: "b" ✅ → path=["aa","b"] → COMPLETE ✅
#   end=3: "aab" ❌ palindrome? No → skip
# Result: [["a","a","b"], ["aa","b"]]

时间复杂度: O(n · 2^n) — 每个字符可以是切割点或不切割

空间复杂度: O(n) 递归栈深度


优化:DP 预处理回文

def partition_optimized(s: str) -> list[list[str]]:
    n = len(s)
    # dp[i][j] = True if s[i..j] is palindrome
    dp = [[False] * n for _ in range(n)]

    for i in range(n - 1, -1, -1):
        for j in range(i, n):
            if s[i] == s[j] and (j - i <= 2 or dp[i+1][j-1]):
                dp[i][j] = True

    result = []
    def backtrack(start, path):
        if start == n:
            result.append(path[:])
            return
        for end in range(start, n):
            if dp[start][end]:  # O(1) lookup instead of O(n) check
                path.append(s[start:end+1])
                backtrack(end + 1, path)
                path.pop()

    backtrack(0, [])
    return result
# Time: O(n * 2^n) worst case, but palindrome check is O(1)

与 Block 其他题的联系 (举一反三)

题目剪枝条件区别
#78 Subsets无剪枝,全取最基础
#39 Combination Sumsum <= target剪枝是数值
#79 Word Search (Day 96)越界/已访问2D + visited
#131 Palindrome (今天)is_palindrome剪枝是字符串属性
#51 N-Queens (下下题)行/列/对角线冲突二维约束

模式总结:回溯的精华不在"回溯本身",在剪枝条件。剪枝越好,性能越好。


📚 References

🧒 ELI5

像拼图:你有一串字母,每次找一段对称的切下来,然后继续处理剩下的。如果某段不对称就跳过那个切法。把所有合法的切法都找出来。

🗣️ 软技能 / Soft Skills — Day 97 (Synthesis)

Expert Phase · New Scenario

新场景:技术债务 vs. 新功能的年度预算争夺战

"你是一个 50 人工程团队的 Staff Engineer。年度规划季节到了,业务方要求 80% 的工程资源投入新功能,但你知道系统技术债务已经导致过去两个季度生产事故增加了 40%。你怎么办?"

这是一道高阶题,考察你同时应对技术判断、商业意识、组织影响力三个维度。


为什么这道题很难

普通工程师只会说:「我们需要还债」。

Senior 工程师会说:「让我们找到平衡点」。

Staff 工程师 会说:「让我把技术风险翻译成业务语言,让 CTO/VP 做有信息的决策」。


STAR 框架拆解

Situation(情境)

量化现状:

  • "过去 2 个季度,P0/P1 事故增加 40%,平均 MTTR(恢复时间)从 45 分钟升至 3 小时"
  • "核心结账模块有 12,000 行无测试的遗留代码,每次修改都需要额外 30% 的开发时间"
  • "三名高级工程师在过去一季度各自花费 ~30% 时间在'应急救火'"

关键:数字比形容词有力。"很多技术债"不如"这季度额外损耗了 2 个工程师·月"。

Task(任务)

你的角色:

  • 不是"说服业务方接受你的方案"
  • 是"帮助所有 stakeholders 做一个信息完整的资源分配决策"

Action(行动)

Step 1: 建立「风险登记册」

技术债务类别 | 业务影响 | 解决成本 | 优先级 结账模块遗留代码 | P0 事故风险 High | 6 人·周 | P0 认证系统版本过期 | 安全漏洞 Medium | 2 人·周 | P1 测试覆盖率 <20% | 发布速度慢 Low | 4 人·周 | P2

Step 2: 将技术风险翻译为业务影响

不说:「我们的数据库连接池要重构」

要说:「如果不解决,下次 Black Friday 流量峰值有 60% 概率导致 2+ 小时宕机,去年此类事故直接损失约 $X 万」

Step 3: 提出可选方案(而非单一答案)

  • 方案A:70% 新功能 / 30% 技术债(推荐)
  • 方案B:50/50 一个季度,之后恢复 80/20
  • 方案C:维持 80/20 但接受风险,签字确认

Step 4: 让业务方做选择

你给的是信息和选项,不是命令。但你要清晰表达每个选项的后果。

Result(结果)

展示结果时强调决策质量,而非仅仅结果:

  • "我们最终选择了方案 A,下个季度事故降低了 60%"
  • "更重要的是,这建立了工程-业务之间的信任框架,之后的规划季我们不再需要为这种争论花 3 周时间"

❌ Bad vs ✅ Good

❌ 坏的回答:

"我跟 VP 说技术债务很重要,他们不听,我很沮丧但还是做了妥协。"

✅ 好的回答:

"我把技术债务翻译成业务语言,用数据建立了风险登记册,主动邀请 VP of Product 参与讨论权衡,最终我们一起做了一个双方都信服的决策。"

Senior/Staff 进阶提示

  • 避免「工程 vs 业务」的对立框架——你是 translator,不是 fighter
  • 预建信任:平时就在 Eng-Product 同步会分享系统健康指标,别等到规划季才「突袭」
  • Rule of thumb:Google、Netflix 工程团队通行标准是 20% 时间投入可靠性/技术基础设施

Key Takeaways

  1. 技术决策要翻译成业务语言,用数字说话
  2. 给选项而非命令,让 stakeholder 做有信息的选择
  3. Staff 的影响力来自建立系统性框架,不是每次单独说服

📚 References

🧒 ELI5

就像你家的管道坏了,你每天用水桶接水(救火)。老板说:我们要建更多房间(新功能)!你要做的不是吵架,而是给老板看:每月因为漏水损失多少钱,修管道只需要多少钱,让他自己算清楚再决定。

🤖 AI — Day 97

AI News Roundup · July 2026

本周 AI 世界大事速览(来源:搜索结果,2026年7月)


📰 本周重要新闻

1. OpenAI GPT-5.6 家族发布 — 三款专用变体

OpenAI 推出 GPT-5.6 家族,三款各有分工:

  • Sol — 重推理任务(类似 o3)
  • Terra — 成本优先(性价比路线)
  • Luna — 速度优先(低延迟场景)

这标志着 frontier 模型开始垂直分化,不再是一个大模型通吃。对工程师意味着:选模型时要根据任务特点匹配,而非默认用最贵的。

来源:rauljitechnologies.com

2. xAI 发布 Grok 4.5,中国 Kimi K3 也来了

Elon Musk 旗下 xAI 发布 Grok 4.5,同期 Moonshot AI 推出 Kimi K3。全球 LLM 竞争格局:美国、中国、欧洲三足鼎立。开源阵营(DeepSeek V4-Pro、MiniMax M3)表现"据报道接近闭源顶级模型"。

来源:champaignmagazine.com

3. Hugging Face 遭 AI Agent 自主攻击

⚠️ 本周最值得工程师关注的安全事件:Hugging Face 检测到一次完全由 AI Agent 自主驱动的基础设施入侵。更戏剧的是,他们用自家 AI 系统检测并分析了这次攻击。

含义:AI agent 的安全边界已经不是理论问题。构建 agent 系统时,需要像对待人类员工一样设权限边界(least privilege principle)。

来源:huggingface.co/blog/security-incident-july-2026

4. AI 价格战加速:Token 成本大降

主要提供商(据报道包括 OpenAI、Meta 等各主流厂商)的 output token 成本大幅下降,使大规模 AI 部署对更多企业变得可行。AI 正从"实验阶段"进入"生产骨干"阶段。

来源:nextmoca.com


🔥 工程师视角:这周学什么?

Agent 安全变成了必修课。构建 agent 系统的工程师,记住这三条:

  1. 最小权限:agent 只能访问它需要的资源
  2. 输入验证:防止 prompt injection / tool abuse
  3. 可观测性:每个 agent 动作都要有日志和审计
# 不好的做法:agent 可以执行任意 shell
def agent_tool(command: str):
    import subprocess
    return subprocess.run(command, shell=True)  # ❌ Dangerous

# 好的做法:白名单 + 沙箱
ALLOWED_TOOLS = {"search", "read_file", "write_file"}
def agent_tool(tool_name: str, params: dict):
    if tool_name not in ALLOWED_TOOLS:
        raise PermissionError(f"Tool {tool_name} not allowed")
    return TOOL_REGISTRY[tool_name](**params)  # ✅ Bounded

📚 References

🧒 ELI5

这周 AI 界发生了三件大事:1) OpenAI 出了三款专用模型,就像厨师刀、菜刀、水果刀各有分工;2) Hugging Face 被一个 AI 机器人偷偷入侵,幸好发现了;3) AI 用起来越来越便宜,大家都开始真正用它干活了。