# 02 · 架构师的思考框架 > 上一章说「架构是在取舍中做重要决策」。这一章给你一套可以照着走的章法,把「拍脑袋」变成「有迹可循」。任何系统,都能用这一套流程拆开。 --- ## 好消息:做架构判断是有章法的 很多人以为,架构判断是种玄学——靠天赋,靠十年踩坑攒出来的「感觉」。这话对了一半:经验确实重要。但**另一半是,顶尖架构师脑子里其实跑着一套相当固定的流程**,只是熟练到自己都没意识到。 我们要做的,就是把这套流程拆出来,让你能**有意识地、一步步地**走。等你走熟了,它也会沉淀成你的「感觉」——但那是建立在章法之上的感觉,而不是凭空的直觉。 这套流程长这样: ``` ┌─────────┐ ┌─────────┐ ┌──────────┐ ┌──────────┐ ┌────────┐ ┌────────┐ │ 需求 │──▶ │ 约束 │──▶ │ 质量属性 │──▶ │ 候选方案 │──▶ │ 取舍 │──▶ │ 决策 │ └─────────┘ └─────────┘ └──────────┘ └──────────┘ └────────┘ └────────┘ 系统要做 有哪些不能 系统要「做 有哪几种 每个方案 选一个, 什么? 逾越的边界? 得多好」? 搭法? 各拿什么 并写下 换什么? 为什么 │ │ └──────────────── 业务/规模变化时,回到起点重走一遍 ◀──────────────────────┘ ``` 注意最下面那条返回的箭头:**这不是一次性走完就结束的流程,而是一个会反复重走的循环。** 业务变了、规模涨了,约束和质量目标就变了,当初的最优解可能就不再最优——架构因此需要演进(这是第 08 章的主题)。 下面我们逐段拆开。**重点会放在第二、三段(约束和质量属性)**,因为那是新人最容易跳过、却最能拉开差距的地方。 --- ## 第一步:需求 —— 但要分清两种需求 一切从需求开始。但**「需求」这个词,藏着架构里最重要的一道分界线**,大多数新人从没注意过: > **功能性需求:系统要「做什么」。** > **非功能性需求(质量属性):系统要「做得多好」。** 这道分界线,值得你刻在脑子里。我们用一个例子把它讲透。 假设需求是:「**做一个能上传图片、并分享给别人看的服务**」。 **功能性需求**(做什么)很容易列: - 用户能上传图片 - 用户能拿到一个链接 - 别人能通过链接看到图片 - 用户能删除自己的图片 这些是「系统得有这些功能」。**但请注意:仅凭这些,你根本没法做架构判断。** 因为—— 「能上传图片」,是给 100 个人用,还是给 10 亿人用? 「别人能看到」,是要求点开秒出,还是转圈三秒也行? 「能分享」,图片要存一辈子,还是七天后自动删? 某个机房着火了,这些图片是可以丢,还是一张都不能少? **这些问题的答案,才真正决定了系统该长什么样。** 而它们,全都是**质量属性**(做得多好): - **性能**:点开图片要在 200 毫秒内显示。 - **可扩展性**:要能从 100 用户平滑长到 10 亿用户。 - **可用性**:全年宕机不超过几分钟。 - **持久性**:图片一旦上传,丢失的概率要极低(比如「十一个九」)。 - **成本**:存十亿张图,不能贵到把公司拖垮。 > **这是架构师最重要的基本功:看到「做什么」,立刻去追问「做得多好」。** > > 功能性需求决定了系统「能不能用」;**质量属性决定了系统「该怎么搭」。** 同样是「上传图片」,要求秒开 + 永不丢失 + 十亿规模,和要求「能用就行 + 个人小工具」,会导出两套完全不同的架构。 > > **一句话:功能性需求是地基的「用途」,质量属性才是地基的「规格」。** 只看用途不看规格,你盖不出对的楼。 为什么新人总跳过质量属性?因为功能性需求是「显性的」——产品经理会写在文档里,白纸黑字。而质量属性是「隐性的」——很少有人主动告诉你「这个要支撑十亿用户、绝不能丢数据」,**你得自己去问出来。** 这正是下一节「问对问题」要解决的事。 --- ## 第二步:约束 —— 你不是在真空里做设计 新人常以为,架构是在追求「理论上最好的方案」。但现实是:**你永远是在一堆「不能逾越的边界」里做设计。** 这些边界,就是约束。 约束和质量属性的区别在于:**质量属性是「你想达到的目标」(越好越好),约束是「你绕不开的限制」(就这条件)。** 一个是你追求的,一个是给你框死的。 常见的约束有这么几类: | 约束 | 它会怎么逼你 | |---|---| | **团队规模** | 三个人的团队硬上几十个微服务?光运维就把人累垮。架构复杂度不能超过团队的驾驭能力。 | | **时间** | 「下周必须上线」和「我们有一年」,会逼出完全不同的方案。时间紧,就得选「现在能交付」的,而不是「理论最优」的。 | | **预算** | 钱决定你能用多少机器、多贵的服务、养多少人。再优雅的方案,烧不起就是空谈。 | | **合规 / 法规** | 「数据必须存在境内」「医疗数据要满足某某标准」——这类约束是**红线**,不是「尽量」,是「必须」,违反了方案直接作废。 | | **已有系统** | 大多数时候你不是从零开始,而是要和一堆「祖传系统」共存。你的设计得迁就它们的接口、它们的脾气。 | | **第三方依赖** | 你依赖的支付网关、云服务、外部 API,它们的能力上限和故障,就是你的约束。 | > **关键认知:约束不是来添堵的,约束是来帮你「砍掉选项」的。** > > 一个没有约束的设计题(「设计一个完美的系统」)其实无从下手,因为选项无穷多。一旦你知道「三个人、三个月、必须合规、要对接老系统」,**绝大多数花哨方案当场出局,真正可行的方案就那么几个。** 约束越清晰,决策越容易。 > > 所以,新接到一个任务时,**先别想方案,先把约束摸清楚。** 摸清约束的人,往往比急着画方案的人,最后做得又快又稳。 --- ## 第三步:质量属性 —— 列一份你的「考量清单」 第一步我们已经明白质量属性有多重要。这一步,给你一份**常见质量属性清单**,作为你每次思考时的「检查表」——不是每一项都重要,而是**逐项过一遍,确保没漏掉那个会要命的**。 | 质量属性 | 一句话解释 | |---|---| | **性能(Performance)** | 系统反应有多快。包括延迟(单次操作多久)和吞吐(单位时间能处理多少)。 | | **可用性(Availability)** | 系统有多大比例的时间是「活着、能用」的。常用「几个九」衡量。 | | **可靠性 / 持久性(Reliability / Durability)** | 数据会不会丢、操作会不会出错。「持久性」特指存进去的数据不会莫名消失。 | | **可扩展性(Scalability)** | 用户/数据涨上来时,系统能不能靠「加机器」从容应对,而不是推倒重来。 | | **一致性(Consistency)** | 多个地方看到的数据是否一致。涉及「刚写的能不能立刻读到」「不同用户看到的是否同一份」。 | | **安全性(Security)** | 能不能挡住攻击、防住越权、保护好敏感数据。 | | **成本(Cost)** | 建设和运营要花多少钱。架构师常常忘了它也是一种「质量」。 | | **可维护性(Maintainability)** | 系统好不好改、好不好懂。新人多久能上手,加个功能要动多少地方。 | | **可观测性(Observability)** | 出了问题,你能不能快速看出「哪里坏了、为什么坏」。 | | **可演进性(Evolvability)** | 业务变化时,架构能不能跟着长大,而不是被锁死。 | 用法很简单:**拿到一个系统,把这张表从头到尾过一遍,对每一项问「它对我这个系统重要吗?目标是多少?」** 比如做一个「内部报表工具」:性能?中等就行。可用性?挂半小时也能忍。一致性?数据准就行,不要求实时。成本?能省则省。——你会发现大部分项要求都不高,这本身就是重要信息:**它告诉你「别过度设计」。** 再比如做一个「支付系统」:一致性?**钱不能算错,最高优先级。** 可靠性?**一笔都不能丢。** 安全性?**红线。** ——同一张表,导出的却是完全不同的侧重。 > 这份清单,正是每个架构模板里**「质量属性表」**的来源。等会儿你去看 [AI 对话产品模板](../templates/ai-chat-product/README.md) 的第 3 节,会看到它列出了「首字延迟、吞吐、成本、可用性、安全」——那就是把这张通用清单,套到「AI 对话」这个具体场景上的结果。**通用框架 + 具体场景 = 那张表。** --- ## 贯穿始终的核心观点:没有银弹,只有取舍 现在到了整套框架的灵魂。如果这一章你只能记住一句话,记住这句: > **没有银弹,只有取舍。任何架构决策,本质都是「用 A 换 B」。** 「银弹」是个老说法,意思是「能一击解决所有问题的万能方案」。在架构里,**银弹不存在。** 每一个让你在某方面变好的选择,几乎都会让你在另一方面变差。 - 想要**更快**?常常要牺牲**成本**(加缓存、加机器)或**一致性**(读到的可能是旧数据)。 - 想要**强一致**?常常要牺牲**性能**和**可用性**(得等所有节点同步好)。 - 想要**高可扩展**?常常要牺牲**简单性**(系统变复杂,运维变难)。 - 想要**快速上线**?常常要牺牲**可维护性**(欠下技术债,以后还)。 ``` 想往这个方向加强 ───▶ 往往要从那个方向割肉 ───────────────────────────────────────── 性能 ▲ 成本 ▼ / 一致性 ▼ 一致性 ▲ 性能 ▼ / 可用性 ▼ 可扩展性 ▲ 简单性 ▼ / 成本 ▼ 安全性 ▲ 便利性 ▼ / 性能 ▼ 上线速度 ▲ 可维护性 ▼(技术债) ``` 这不是说做架构很悲观,恰恰相反:**当你接受「凡事皆有代价」,你就从「找最好的方案」(找不到)转向了「找最合适的取舍」(找得到)。** 后者才是真正的架构工作。 > **由此引出一条极其有用的判断标准:** > > **如果有人给你一个方案,说它「哪儿都好,没有任何缺点」——那不是因为方案完美,而是因为他没想清楚。** > > 一个想清楚了的人,一定能告诉你「这个方案好在哪、同时牺牲了什么、为什么这个牺牲值得」。**看得到取舍,是想清楚了的标志;看不到取舍,是没想清楚的标志。** 你评估别人的方案、或者审视自己的方案时,这一条几乎是万能的试金石。 --- ## 怎么走完这套框架?关键是「问对问题」 框架是骨架,真正让它转起来的,是**提问**。前面说过,质量属性和约束大多是「隐性的」,得靠你问出来。所以,**会问问题,是架构师的核心手艺。** 下面这几个问题,几乎适用于任何系统。拿到一个新需求,先把它们问一遍: ``` ┌────────────────────────────────────────────────────────────┐ │ 架构师的「灵魂六问」 │ ├────────────────────────────────────────────────────────────┤ │ 1. 规模多大? 现在多少用户/数据?峰值多少? │ │ 2. 读写比? 是读多写少,还是写多读少? │ │ 3. 一致性要求? 刚写的必须立刻能读到吗?能容忍短暂不一致吗? │ │ 4. 增长预期? 一年后会涨到多少?是平缓还是会爆发? │ │ 5. 失败的代价? 这个东西挂了/数据丢了,后果有多严重? │ │ 6. 有什么约束? 团队多大?多少时间?多少预算?有无合规? │ └────────────────────────────────────────────────────────────┘ ``` 为什么是这六个?因为它们每一个,都直接锚定一类架构决策: - **规模**和**增长**,决定你要不要、何时要为「扩展」做准备。 - **读写比**,决定你的系统该往「读优化」还是「写优化」倾斜(这会深刻影响数据怎么存,见第 05 章)。 - **一致性要求**,决定了那个最经典、最折磨人的取舍:一致性 vs 性能/可用性。 - **失败的代价**,决定你要在可靠性、可用性上投入多少——「丢了无所谓」和「丢一条就出大事」是两个世界。 > 这六问背后,藏着一个新人很难内化、但极其重要的心法:**没有「最好的架构」,只有「在这组答案下最合适的架构」。** > > 同样是「聊天功能」,做一个三个人用的内部工具,和做一个十亿人用的微信,答案天差地别——不是因为后者的工程师更厉害,而是因为**两者的六问答案完全不同**。所以,**别一上来就找「正确答案」,先把你的六问答清楚;答案变了,最优解就变了。** --- ## 走一遍完整流程:设计一个「短链接服务」 讲了这么多,我们拿一个经典又小巧的例子,完整走一遍框架。**注意我们的目标不是给出「标准答案」,而是演示「怎么想」。** 需求:「**做一个短链接服务,把长网址变成 `short.ly/x7Kp9` 这样的短链,点击后跳转到原网址。**」(就是各种「短网址生成器」) ### ① 需求:先分功能 vs 质量 **功能性需求**(做什么): - 输入一个长 URL,生成一个短 URL - 访问短 URL,跳转到对应的长 URL - (可能)统计每个短链被点了多少次 就这么三条,简单到几乎没什么可设计的。**真正的设计,藏在质量属性里。** 于是我们开始问。 ### ② 问对问题(灵魂六问) - **规模多大?** 假设我们对标一个中等服务:每天新建 1000 万条短链。 - **读写比?** 关键洞察来了——**短链是「生成一次,被点击无数次」的。** 一条链接可能被分享后点几百万次。所以**读(跳转)远远多于写(生成)**,读写比可能是 100:1 甚至 1000:1。 - **一致性要求?** 「刚生成的短链,要能立刻访问吗?」——最好能,但**晚个一两秒也能忍**(你刚生成完,通常不会真有人在那一瞬间就去点)。这是个重要的「松一点」的信号。 - **增长预期?** 链接只增不减,**数据会无限累积**。十年下来是个天文数字,得想好怎么存。 - **失败的代价?** 「跳转挂了」用户点不开链接,体验差但不致命;「数据丢了」——已经分享出去的短链全部失效,**这是灾难,持久性要求高**。 - **约束?** 假设是个小团队、要尽快上线、预算有限。 ### ③ 从答案里,质量属性自己浮现出来 把六问的答案翻译成质量目标: | 质量属性 | 目标 | 来自哪个回答 | |---|---|---| | **读性能** | 跳转要极快(< 50ms) | 读远多于写,跳转是核心体验 | | **可扩展性(读)** | 要扛住海量读请求 | 读写比 100:1+,峰值在「读」 | | **持久性** | 短链绝不能丢 | 失败代价:丢了等于已分享的链接全废 | | **一致性** | 可以「最终一致」 | 晚一两秒能访问到,用户能忍 | | **成本** | 存储要省 | 数据无限累积 + 预算有限 | **看到了吗?** 三条朴素的功能需求,经过「问对问题」,长出了一张清晰的质量目标表。**这张表,才是后面所有决策的依据。** ### ④ 候选方案 & 取舍 现在带着这张表,我们看几个关键决策点,**每一个都是一次取舍**: **决策 A:短码怎么生成?** - 方案一:对长 URL 做哈希,取前几位当短码。简单,但**会撞车**(不同 URL 哈希到同一个码),得额外处理冲突。 - 方案二:用一个全局递增的计数器,把数字转成更短的字符表示。**不会撞车**,但需要一个「全局发号」的部件,这本身在高并发下是个挑战。 - *取舍*:方案一简单但要处理冲突;方案二干净但引入了「发号器」这个新的复杂点和潜在瓶颈。**没有免费的午餐——选哪个,取决于你更怕「处理冲突的麻烦」还是「维护发号器的麻烦」。** **决策 B:怎么扛住海量的「读」?** - 我们的读写比是 100:1+,而且**热门链接会被反复点**。 - 这几乎是在向你喊:**加缓存。** 把热门短链的映射放进内存缓存,绝大多数跳转请求根本不用碰数据库。 - *取舍*:缓存让读变得飞快、还省了数据库压力(对上我们的「读性能」和「成本」目标),**代价是多了一层要维护的东西**,以及「缓存里是旧数据怎么办」的问题——好在我们前面问出了「能容忍最终一致」,所以这个代价我们**承受得起**。看,前面问对的问题,在这里直接帮我们拍了板。 **决策 C:数据放哪、怎么存?** - 数据形态极其简单:就是「短码 → 长 URL」的键值对应,而且**几乎只按短码来查**。 - 这种「简单键值、按 key 查、要海量、要快」的形态,天然适合键值型存储,而不是把它硬塞进复杂的关系型结构。 - *取舍*:这正是「**数据的访问形态决定存储选择**」这条通用原则的体现(下一章和第 05 章会反复出现)。 ### ⑤ 决策 & 记下「为什么」 走到这里,你不只得到了一个方案,更重要的是——**你能说清每个决策的理由和代价了:** > 「我们用缓存扛读,**因为**读写比悬殊且能容忍最终一致;**代价**是多一层维护和短暂的旧数据,**但这个代价我们前面确认过能接受**。我们用键值存储,**因为**数据形态是简单的按 key 查询。我们短码用 X 方案,**因为**……」 **这,就是架构判断。** 它和「我随便选了个数据库就开干」的区别,不在于用了什么技术,而在于**每一步背后都有「为什么」和「代价」**。把这些「为什么」记下来,就是第 08 章要讲的 ADR(架构决策记录)。 --- ## 📌 真实案例:这套框架不是纸上谈兵 本章用「短链接服务」走了一遍六问。真实世界里的短链(**Bitly**、**TinyURL** 等)正是这么设计的:读写比悬殊、重度缓存、KV 存储、唯一 ID 发号。 - 想看这套框架产出的「成品」,直接对照本仓库 [短链接服务模板](../templates/url-shortener/README.md)——它的第 3 节(需求与约束)和第 8 节(关键决策)就是本章「六问 + 取舍」走到底的结果。 --- ## 🎯 随堂检验 --- ## 本章小结 - **做架构判断有章法:需求 → 约束 → 质量属性 → 候选方案 → 取舍 → 决策**,而且业务一变,就回到起点重走一遍。 - **架构师最重要的基本功,是分清功能性需求(做什么)和质量属性(做得多好)。** 功能决定「能不能用」,质量属性决定「该怎么搭」。前者显性、写在文档里;后者隐性、得自己问出来。 - **约束不是来添堵的,是来帮你砍选项的。** 团队、时间、预算、合规、已有系统、第三方依赖——摸清约束,可行方案就剩没几个了。 - **没有银弹,只有取舍。任何决策都是用 A 换 B。** 一个「哪儿都好、没有缺点」的方案,不是完美,是没想清楚。**看得到取舍 = 想清楚了。** - **会问问题是核心手艺。** 灵魂六问:规模、读写比、一致性、增长、失败代价、约束。**没有最好的架构,只有在这组答案下最合适的架构。** - 短链接的例子告诉我们:**三条朴素的功能需求,经过「问对问题」,能长出一张清晰的质量目标表,而那张表才是一切决策的依据。** --- > 这套框架,正好对应每个架构模板里的两个核心小节:**「核心需求与约束」**(对应本章的需求/约束/质量属性)和**「关键架构决策与权衡」**(对应本章的候选方案/取舍/决策)。 > > **现在就去验证一下:** 翻开 [`../templates/`](../templates/README.md) 里任意一个模板,直接看它的第 3 节和第 8 节,你会发现它们就是这套框架的实际产物。试着用本章的「灵魂六问」反推:它的设计者当初一定问过这些问题。 > > 想清楚之后,你还得把它**讲清楚**——让团队里每个人都看懂你脑子里的系统。这就需要会画图。 > > 👉 继续阅读:[03 · 读懂与画好架构图](03-读懂与画好架构图.md)