Skip to content

架构案例与解决方案沉淀 ​

S8-005选修高级约 60 分钟JDK 21持续学习 · 技术资产与输出

1. 本节定位 ​

做过 ≠ 会做 —— 只有把「一次排查/优化」沉淀成可检索、可复用的卡片,经验才真正属于你。

★ 本节用工具把三个真实案例(全部来自本知识库的实测)固化成解决方案卡 ✓✓:

text
卡片 1:内存持续增长直到 OOM —— 先用存活量趋势定性,再定位泄漏点
卡片 2:接口偶发卡顿        —— 先看线程栈与死锁,再谈优化
卡片 3:秒杀超卖            —— 先挡流量,再谈一致性
每张卡:现象 / 影响面 / 排查过程 / 根因 / 方案 / 验证 / 适用边界 / 复盘(八字段)✓✓✓

★ 工具:python -X utf8 scripts/growth/solution_card.py ✓

2. 学习目标 ​

  • 掌握解决方案卡的八字段结构 ★★★;
  • 会把一次排查固化成卡片(含「适用边界」)★★★;
  • 理解 ADR(架构决策记录)与解决方案卡的分工 ★★★;
  • 能建立个人的「可检索经验库」★★。

3. 前置知识检查 ​

4. 为什么需要这个知识 ​

★ 两种知识流失 ✗✗:

流失后果
个人:排查完就忘 ✗✗三个月后遇到同类问题,又从头查一遍
团队:经验在人脑里 ✗✗✗换个人就"没人知道怎么搞"

★★ 沉淀的价值 ✓✓✓:把「一次性经验」变成「团队可检索的条目」 —— 下次遇到类似现象:先搜卡片,再动手(平均定位时间可以减半)✓✓。

5. 核心概念 ​

5.1 解决方案卡:八字段模板(实测)★★★ ​

字段回答的问题为什么必须有
现象观察到什么(含曲线/报错)检索入口 ✓✓
影响面稳定性 / 正确性?谁受影响定级与上报 ✓
排查过程一条条命令与结论可复现的路径 ✓✓✓
根因一句话说透决定方案是否治本 ✓✓✓
方案改了什么(代码/配置)可执行 ✓
验证怎么证明修好了防"感觉修好了" ✓✓
适用边界什么情况不适用防误用 ✓✓✓
复盘一句话教训组织记忆 ✓

★ 实测卡 1(节选) ✓✓✓:

text
  现象:服务运行数小时后 OOM(Java heap space);堆使用曲线只涨不跌;重启后复现
  排查过程:
    · 开启 -Xlog:gc*:file=,观察每次 GC 后的存活量(不是使用量)
    · 发现:存活量 61M → 63M 反复顶住 64M 上限,Full GC(G1 Compaction Pause)5 次
    · 结论:对象「回收不掉」,不是「分配太快」
  根因:缓存没有上限与淘汰策略:**存活对象永远不会被任何收集器释放**
  适用边界:适用「存活量单调上涨」;若存活量平稳但停顿长,是另一类问题(调收集器/堆)

5.2 从三张卡提炼的通用模式(实测)★★★ ​

text
· 定性先行:先用指标把问题分类(泄漏 / 锁 / 过载),再选工具 ✓✓
· 双重验证:一手日志(GC 日志、线程栈)+ 最小复现,缺一不可 ✓✓✓
· 改完必验:用同一流量回归,给出前后对比数字 ✓✓
· 沉淀边界:写清「什么情况不适用」,避免下次误用 ✓✓✓

★★ 模式的用法 ✓✓:新问题先匹配模式("这像不像卡片 3 的过载型?")—— 匹配错了再换方向,比盲目试工具快得多 ✓✓✓。

5.3 解决方案卡 vs ADR(两者都要)★★★ ​

解决方案卡ADR(架构决策记录)
回答"这类问题怎么解""当初为什么这么决策" ✓
触发一次排查/优化完成后一个决策做出时 ✓
结构八字段(现象 → 复盘)背景 / 决策 / 备选方案 / 后果 / 状态 ✓
例子"存活量上涨 = 代码问题""为什么锁定 JDK 21 而不是 17"✓
复用场景排障(搜索现象)评审(解释历史)✓✓

★ ADR 的最小格式 ✓✓:一段背景 + 一个决策 + 至少两个备选与淘汰理由 + 后果(含代价) —— 「为什么不选另一个」是 ADR 的灵魂 ✓(与 《系统设计题》 的面试答题同源)。

5.4 沉淀的时机与渠道 ★★ ​

时机动作
排查结束 24 小时内 ✓✓趁记忆鲜活写卡片(复用 《模拟面试与面试复盘》 的复盘习惯)
决策做出时 ✓当场写 ADR(一段即可,别追求仪式感)
每季度 ✓翻一遍卡片库,把重复出现的模式提炼成"清单"

★ 渠道 ✓:团队 wiki(共享)+ 个人笔记(私有补充)—— 两处都要有 ✓✓。

6. 递进示例 ​

6.1 写一张卡(最小流程) ​

text
① 现象一句话(含关键数字:64M / Full GC 5 次 / OOM)
② 排查过程按时间线列命令与结论(3-5 条)
③ 根因一句话 + 方案一句话
④ 验证方式(同流量回归 + 观察指标)
⑤ **边界与复盘**(最容易被省略、但最有价值)✓✓✓

6.2 写一条 ADR ​

text
背景:GC 默认 G1、堆 128M 的场景下 Serial 停顿更短(实测 0.591ms vs 1.590ms)
决策:小堆服务显式指定 -XX:+UseSerialGC
备选:G1(默认,但小堆不占优)✗;Parallel(吞吐优先,延迟不敏感场景可选)
后果:单次停顿更短;代价是**大堆场景必须换回 G1**(边界写明)✓✓

6.3 反例:把 wiki 写成流水账 ​

text
"2026-09-23 处理了一个 OOM,重启后好了" ✗✗(没有根因、没有验证、没有边界)
—— 这种记录三个月后等于没有 ✓✓

7. 完整可运行工具与实测 ​

工具:scripts/growth/solution_card.py

运行:

powershell
python -X utf8 scripts/growth/solution_card.py

实测输出(节选):

text
--- 卡片 2:接口偶发卡顿:先看线程栈与死锁,再谈优化 ---
  现象:部分请求卡住不返回;CPU 不高但吞吐下降;重启后缓解、过一阵复发
  排查过程:
    · jcmd <pid> Thread.print(或 Arthas thread -b)找阻塞关系
    · 发现两个线程互相等待对方持有的锁(Found one Java-level deadlock)
  根因:**锁顺序不一致**:不同代码路径以不同顺序获取同一组锁
  适用边界:只解决「锁顺序」型死锁;线程池耗尽、下游超时不属于此类

8. Debug 观察点 ​

  1. 把你最近一次排查写成卡片,逐字段检查是否"填满"(缺边界 = 不合格)✓✓✓;
  2. 用卡片去匹配一个新问题:匹配错了在哪里?把这次也写成一条 ✓✓;
  3. 把一张卡给同事读:他能否照着"排查过程"复现?✓✓;
  4. 三个月后回看卡片:还能直接上手吗?(检验沉淀质量)✓。

9. 常见错误 ​

#错误说明
1只记结论不记过程 ✗✗无法复现,也教不会别人 ✓✓
2不写适用边界 ✗✗✗下次可能误用到不适用的场景 ✓✓
3写完不验证 ✗✗"感觉修好了"是最贵的错觉 ✓✓
4拖到月底补记 ✗细节全忘 ✓
5ADR 写成流程文档 ✗ADR 只讲「选什么 + 为什么不选另一个」✓✓
6只存个人笔记 ✗团队检索不到 = 没沉淀 ✓

10. 动手实验 ​

  1. 跑 solution_card.py,读懂八字段 ✓✓;
  2. 为你的项目写 2 张解决方案卡 + 1 条 ADR ✓✓✓;
  3. 建一个「模式清单」:把卡片按「现象类型」归类(泄漏 / 锁 / 过载 / 配置)✓✓;
  4. 每季度回扫一次,把反复出现的模式升级为团队 Runbook ✓✓。

验收方式:产出一张八字段齐全(尤其边界与验证)的解决方案卡,且同事能照它复现排查路径。

扩展任务:把本知识库 S6 的实测整理成一本《线上问题排查手册》(按现象索引)✓✓

11. 练习题 ​

  1. 解决方案卡的八字段?哪三个最容易被省略?
  2. 解决方案卡与 ADR 的分工?
  3. 「定性先行」为什么比「选工具」更重要?
  4. 为什么必须写「适用边界」?
  5. 沉淀的最佳时机与渠道?
参考答案(要点)
  1. 现象/影响面/过程/根因/方案/验证/边界/复盘;验证、边界、复盘最常被省 ✓✓★
  2. 卡片答「这类问题怎么解」;ADR 答「当初为什么这么决策」✓✓★
  3. 先分类(泄漏/锁/过载)才能选对工具,否则是盲目试错 ✓✓★
  4. 防误用:同类现象可能根因不同 ✓✓★
  5. 24 小时内(记忆鲜活);团队 wiki + 个人笔记双渠道 ✓✓★

12. 掌握标准 ​

  • [ ] 会用八字段写解决方案卡 ★★★;
  • [ ] 会写最小 ADR(含备选与淘汰理由)★★★;
  • [ ] 能提炼「模式清单」★★★;
  • [ ] 有 24 小时内沉淀的习惯 ★★。

13. 扩展资源 ​

14. 下一步学习 ​

《团队分享与知识输出》 团队分享与知识输出 —— 把沉淀的卡片讲出去,形成团队资产。

前置知识

无,可直接开始

后续知识

暂无

进度只保存在本机浏览器,可随时清除

个人学习项目:AI 生成内容均经人工复核,第三方资源仅作索引