架构设计这词,我在不同场合被问过太多次,问的人从刚带项目的初级工程师到要拍板技术路线的负责人都有。大家最常说的困惑出奇一致:不是不知道怎么画框图,也不是不知道要拆模块、分层、做接口,而是真到了那几个决定项目走向的岔路口,两边都有道理,怎么选都疼。技术方案里最麻烦的从来不是“能不能实现”,而是“这么实现下去,三个月后、一年后、三年后,我们扛不扛得住”。架构设计的本质不是画出一张漂亮的静态结构图,而是一连串敏感点(sensitivity point)上的权衡(trade-off)。这篇内容,我把自己在这些岔路口反复踩出来的经验摊开讲,包括哪些地方最容易埋雷、为什么同一套决策换个业务场景结论就完全反过来、以及我自己现在做取舍时实际会过的那些筛子。
1. 先拆清楚:敏感点和权衡点不是一回事,但总被混着谈
很多人一聊架构,就把“敏感点”和“权衡点”搅在一起。我自己的分法是这样:敏感点是架构里某个具体特征对特定变化有多“脆”,衡量的是影响范围;权衡点是两个或多个目标互相拉扯时你不得不做的取舍,衡量的是优先级排序。前者说的是如果一个地方动了,地震波会传到多远;后者说的是你愿意用哪些指标去换哪些指标。
1.1 打个比方:敏感点像承重墙,权衡点像装修预算
你拿到一套房子,屋里哪些墙能砸、哪些不能砸,这堵墙一动整栋楼都跟着抖,这就是敏感点。墙体结构、承重位置、管线走向,就是这套房子的架构敏感点。而权衡点呢,更像是装修预算——你手里就这么多钱,装了大理石地面就没钱做全屋智能,选了中央空调就得压缩柜子空间。预算分配的取舍,就是权衡。
架构敏感点的经典例子:你把核心交易链路做成强一致性的同步调用,那么数据库写入能力就是一堵承重墙。一旦业务量上来,你以为只要加个缓存就能扛,但实际上缓存只能挡读流量,写流量依旧直扑数据库,你根本没绕开这堵墙。这种设计下,数据库性能就成了整条链路的敏感点——无论其他模块优化得多么天花乱坠,只要库还是那个库,瓶颈就不会消失。
架构权衡点的经典例子:为了接受更高的并发,你允许订单状态在极端场景下短暂不一致,最终一致;这就是用一致性去换可用性。相反,有些资金类场景你宁可损失部分可用性也要守住强一致。这两者间没有绝对正确的算法答案,只有结合业务语境做出的优先级判断。
把这两个概念拆明白再往下去看,就清楚为什么很多架构评审会上争了半天其实是在鸡同鸭讲——一边说的是“这堵承重墙会害死我们”,另一边说的是“可我就这点预算”,他们压根在讨论不同层面的问题。
1.2 为什么架构里最贵的错误都发生在敏感点上
我做技术评审这些年,一个越来越强烈的体会是:权衡选错还可以靠后续演进慢慢找补,敏感点放错了位置则很可能直接把项目钉死在特定规模或形态上,后面想翻盘就得推倒重来。
举个例子。一个面向企业内部几十人用的小系统,当初架构里把业务规则全部写在存储过程里,出库逻辑、价格计算、审批流全在数据库端完成。最初开发效率奇高,一个后端工程师加一个DBA能搞定所有迭代。后来企业做数字化转型,这套系统要对外开放API,要支持多端接入,要求业务逻辑沉淀成服务化接口。这时候发现所有核心规则都锁死在存储过程里,要抽出来得重写一遍业务层,还要处理几百个存储过程之间隐含的相互调用。数据库里的存储过程体系,从当初的“快速实现方案”变成了后来的架构敏感点——业务能力全部被它卡住,任何改动都要过一遍这个笨重的旧核心。
反过来,很多人在不需要的时候过早引入微服务,同样是在造敏感点——服务划分、网络通信、数据一致性、分布式事务、链路追踪,整套复杂度全是你自己给自己加的承重墙。一个日活几千的后台管理系统,单体应用五分钟能改完上线的功能,拆成微服务之后要跨服务联调、发版对齐、排查分布式调用链,把一个本身没有并发压力的系统硬生生做出了高并发系统才有的运维成本。
所以我做架构评审,第一眼看当前的敏感点设在哪里,而不是先看技术栈新不新、用了多少中间件、框图画得有多对称。敏感点如果搁在脆弱的、不易演进的位置,它在未来某个时间点一定会在你最不想它出事的时候出事。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 最常见也最要命的权衡:一致性和可用性之间没有中间态
分布式系统设计里最经典的一组权衡,是CAP里的C和A之争。初学的时候觉得这道理太简单了——网络分区发生时,要么保一致牺牲可用,要么保可用牺牲一致。但真到了业务设计里,“到底选哪个”根本不是一个一次性决策,它需要被拆到每条数据、每次操作、每个异常场景下去反复判断。
2.1 一个库存扣减案例的两种极端解法
先说业务背景:一个电商平台的库存扣减。库存数字是绝对的硬约束吗?不同场景答案完全不同。
闪购秒杀场景,超卖一件都是事故。你宁可部分用户刷出“活动太火爆”也不愿让用户下单成功却发不出货。这种场景没有商量余地,库存在数据库里做乐观锁控制,update stock set stock = stock - 1 where id = ? and stock > 0,影响的update行数为0就返回失败。所有方案都要往这个强一致约束上靠,事务、锁、重试机制全都围绕库存准确性兜底。这就是一致性优先。
但同样是库存扣减,放在一个普通SKU的加购场景里,展示页告诉用户“仅剩5件”,这个数字就未必需要毫秒级强一致。它是运营策略的一部分——可能故意显示少一点制造紧迫感,也可能因为多渠道销售导致展示数据有几秒钟延迟。用户完全不感知。这时候拿一个超高成本的强一致方案去保障“前台展示量与实际库存一致到毫秒级”,就是拿大炮打蚊子,纯粹的浪费。
所以这批数据、这个操作的C和A怎么权衡,要看它处在业务的哪个位置:是资金、是合规、是用户可见的核心承诺,还是仅有参考意义的运营指标。前者必须让一致性优先,后者应理直气壮地把可用性、成本和性能放在更前面。
2.2 最终一致性的“最终”到底要等多久
选了最终一致,就要定义“最终”的上限。很多架构师在评审时说“我们用异步消息最终一致”,但这句承诺如果没有具体数字边界,团队根本没法验证和兜底。
我的习惯是把最终一致性拆成三层来约定:
- 延迟预算:正常情况下,数据从生产端写到消费端可见,目标几秒内完成。超出预算必须告警。比如订单支付成功后通知积分系统加分,支付回调与积分入账之间,常规延迟阈值定义为5秒,超过就上告警。
- 对账兜底:最终一致的“最终”不能完全依赖消息不丢、不重、顺序不乱,因为这些东西在分布式环境下永远可能出意外。更稳妥的设计是定期全量对账,比对生产端和消费端的数据差异,自动补偿差异数据。做得好的人,核心链路都有一张对账任务表,定期扫出状态不一致的数据去重新驱动补偿。
- 面向用户的表达:数据暂时不一致期间,用户在界面看到什么状态、怎么提示,也需要设计。你不可能让用户看着“积分到账失败”之类的血红大字干着急,产品设计上可以在交易详情里写“积分预计24小时内到账”,就算背后真的补偿了三四次,用户层面始终是稳定可信的。
没有延迟预算、没有对账兜底、没有用户侧表达的最终一致,是最危险的方案——它只是在理论上“最终会一致”,实际上出了问题没人知道、没人发现、没人处理。这种方案在PPT里讲得通,在线上事故复盘会上完全站不住脚。
2.3 我理想中的一致性分级策略
现在我做业务系统,第一件事是拉着产品和运营把所有核心数据逐个过一遍,从两个维度打标签:一个维度是“不一致窗口能容忍多久”,另一个维度是“不一致是否会造成资损/合规风险/用户投诉”。
表格化地梳理下来,所有数据操作都能大概分成四档:
| 数据场景 | 容忍延迟 | 主要风险 | 推荐的实现方式 |
|---|---|---|---|
| 支付金额、余额变动 | 近似0容忍 | 资损、合规 | 强一致事务 + 数据库锁/乐观锁 |
| 订单状态流转 | 秒级以内 | 用户体验、客服投诉 | 分布式事务框架,或同步核心状态 + 异步解耦次要数据 |
| 积分、优惠券发放 | 秒到分钟级 | 中低 | 异步消息最终一致 + 对账补偿 |
| 用户行为分析、推荐数据 | 小时级甚至天级 | 很低 | 离线批处理 / T+1同步,不上实时链路 |
数据先分好级,再去谈具体技术——不要一上来就想用哪种方案。分级本身就是最重要的架构活动。写代码之前先花一块白板把核心数据流和分档表画出来,比什么花哨设计都实用。
3. 范围蔓延和过度设计:从“现在”到“未来”的距离决定架构的胖瘦
架构设计里另一个高频纠结,是做多大规模。大公司出来的工程师容易把架构画得极其复杂,因为他们见过的场面大;小公司出来的工程师容易设计得过于简陋,因为他们没经历过业务爆炸的痛。两种风格在评审会上又往往会互相看不惯。但架构应该长多大,只取决于一个变量——从现在到你以为的那个未来,中间隔着多少真实的业务步骤。
3.1 YAGNI和防御性设计的拉锯战
YAGNI(You Aren't Gonna Need It)原则说:永远不要为现在用不到的功能写代码。这句话单独拎出来是对的,但它被滥用了——很多人把“不为现在用不到的功能写代码”理解成了“不为未来可能发生的演进做任何结构性预留”。这是两码事。不为不需要的功能写代码,不代表可以忽视业务方向已经显现出的演进趋势。
我自己的判断方式,是把未来的需求分成两类:
- 已经出现在路线图上的明确需求,哪怕是两个月后才做,架构上就要给它留位置。比如你清楚下个季度要接入一条新的支付渠道,那么现在设计支付模块时就应该把“渠道抽象”做进去,不然后面接一家渠道就要改一次核心流程。
- 凭空想象的未来需求,比如“万一我们以后要做千万级用户社交平台怎么办”,这种没有明确业务信号支撑的假设,不要为它增加任何复杂度。
防御性设计的核心要留给那些变化方向明确、变化成本极高的地方。比如数据模型的主键设计、核心交易链路的幂等框架、资金账务的流水记录方式,这些位置预留一点设计余量回报率极高;而业务展示层那些花样繁多功能,未来要改就让产品改,代码该重构就重构,反而更务农。
3.2 想扛住未来流量:先分清“加机器能解决”和“只能靠架构解决”
很多架构师设计高并发方案时,心里默认“未来一定会有海量流量”,为此一开始就上分库分表、上各种复杂的分布式架构。这里有个认知盲区——大部分增长,其实可以通过“加机器 + 做缓存 + 优化慢查询”扛过去。
MySQL单库在合理索引和缓存配合下扛几千QPS的读写没大问题,再往上做读写分离、加缓存层,撑几万QPS也有成熟套路。真正必须从架构层面解决问题的场景,通常是下面几类:
- 单库单表的数据量到了千万级以上,索引效率和写入性能明显劣化,这已经不是加机器能改变的了。
- 单一存储无法同时满足多种查询模式,需要引入专门的搜索引擎、列式存储或宽表。
- 核心链路的响应时间被串行依赖卡死,必须用异步化消灭长链路中的等待。
- 单点故障会直接导致整体业务不可用,需要从部署架构层面做冗余。
如果你的系统还在不需要这些架构手段的阶段,提前把它们做进去,不仅没解决任何当前问题,还给后续开发迭代绑上了一层厚厚的手铐脚镣。每次写一个查询都要考虑“数据在哪个分片”“跨分片怎么聚合”,研发效率想高都难。我的看法是:把架构设计成未来三年内够用、且关键路径上不被卡死,就足够了。真到了分库分表那天,业务规模能撑起这笔重构成本,那时候才是做这件事的正确时机。
3.3 我见过的“未来适应性”灾难现场
讲个具体案例,某项目为了“将来系统一定能无限扩展”,一开始就按多租户、跨地域部署的大平台来设计。租户维度被放进了每张业务表、每个查询条件里,所有数据访问都套了一层租户上下文。项目做了大半年后,真实的业务模型其实只有一个客户在用,而且未来很长一段时间也看不到第二个客户。这套“多租户”架构没有带来任何收益,却让每一次联表查询都变复杂,每一条缓存key都要考虑租户维度,缓存命中率还被强行切碎。后来实在忍不了,回退成单租户架构,数据层重构了一个多月。
这不是说多租户架构有问题,而是这个团队把“未来可能会多租户”当成了“现在就要做成多租户”。架构上的未来适应性应该是确保未来的变化能被隔离在某一个模块内,而不是让未来可能的需求绑住现在的每一个设计决策。
4. 分布式链条上的隐藏敏感点:幂等、缓存与异步化
细节里藏着魔鬼。很多系统宏观架构没问题,但微观设计上踩着下面这几个大坑——它们看似只是某个小点,实际是整个系统的隐藏敏感点,不经意间就能把整体架构拖垮。
4.1 幂等:分布式系统的第一默认设计
先问一句:你们的核心写操作默认支持幂等吗?如果答案不是“默认支持,只有明确知道不需要幂等的情况才除外”,那这个系统离事故就差一次网络超时重试的距离。
网络超时是分布式环境中的常态。一个订单创建请求发出后,客户端迟迟没收到响应。用户等不及,点了一下重试按钮。如果服务端接口不是幂等的,第一笔订单已经写进去了,第二次重试又创建了一笔新订单,用户一不留神就产生了重复购买。这就是典型的需要幂等保护的位置。
实际做幂等,我的建议是三步走:
- 识别天然幂等的操作:比如
将订单状态置为已取消,本身就是天然幂等的——再多次执行结果都一样,无需额外处理。 - 为天然非幂等的操作设计幂等键:订单创建、支付回调、积分发放这类操作,应由调用方生成唯一业务键(如
orderId、paymentId),服务端通过唯一索引或Redis分布式锁做去重判断。 - 把幂等校验和核心业务放同一个本地事务里:不要先查一次“这个订单是否已处理”,判断完再开事务去处理,两个步骤间有并发空隙,重复请求可能同时通过校验。更稳妥的是把幂等键作为唯一索引建进表里,利用数据库约束从根本上拦掉重复数据,插入冲突就直接按“已处理过”返回。
幂等性这套设计,不能等出了重复订单事故再补。初始设计时不补,后面线上第一起重复支付事故大概率就是这么来的。
4.2 缓存:性能利器与一致性黑洞并存
缓存是所有架构师都爱用的提速神器,也几乎是线上故障的最大策源地。先加缓存,后补一致性方案这种本末倒置的操作,在现实里实在太常见了。
常见的坑有三类:
- 只设过期时间没做主动更新:业务每次写数据后只更新数据库,缓存等过期了才失效。在这段窗口里,用户读到的全是旧的。稍微聪明点的做法是写操作后主动删除缓存,下次读时再回源数据库重建。删除比更新好——更新可能遇到并发写导致缓存和数据库顺序错乱,删掉让下一次读去拉最新值,天然避免旧数据残留。
- 缓存雪崩:大量缓存key在同一时间段集中失效,请求全部穿透到数据库,把库打挂。解决方式很多,最简单有效的就是过期时间加随机偏移量,别让key整整齐齐一起失效。
- 缓存击穿:一个热点key在过期瞬间被大量并发请求同时回源。可以在回源逻辑上加互斥锁,只放一个请求去查库,其余请求等锁后直接读新缓存。
缓存设计更微妙的一点是:缓存的内容边界在哪里。把数据库行拿去缓存简单直接,但这种缓存对“多个维度查询”的适配性很差,不同查询条件必然各自维护key、各自有各自的更新一致性。稍微复杂一点的数据,我喜欢在缓存里存“组装后的视图模型”而不是裸数据行——一次缓存命中直接返回前端需要的完整结构,不仅快还减少多次回源。但这要求写数据时对视图模型的更新逻辑有足够清晰的把握,不然很容易出现缓存里的视图模型跟库里的原始数据对不上。
4.3 异步化:解耦利器也可能是隐性地雷
异步消息是解决同步链路过长、响应缓慢的一把好手,但它天然引入了更多的分布式不确定性。用RabbitMQ或Kafka做异步解耦时,至少几个点要提前想清楚:
- 消费失败后的重试与退避策略:重试多少次?间隔多少?重试超过上限之后是进死信还是落本地表人工处理?每次消费失败都希望能有自动化兜底,千万别等到上手工删消息、改库状态。
- 消费者的幂等:异步消息天然可能被重复投递,尤其消费端处理超时后服务端会重新发送。所以消费者处理消息前必须先做幂等判断。
- 消息积压监控:积压量是异步系统的体温计。必须给每个关键topic配上积压告警阈值,积压超过某个量就说明消费链路出问题了,要及时介入。
- 消息体设计要预留扩展字段:不要只把一两个业务ID塞进消息里,后面任何扩展都要消费者改代码、重新发历史消息。消息体里保留一个
Map<String, Object> extra之类扩展字段,成本极低,将来能省很多沟通和升级的麻烦。
异步化不是把同步调用换掉就完事,它把“调用失败立即知道”这种便利换成了“失败后要靠一套机制去发现、去补偿”。没有配套监控、重试、幂等、对账机制的异步化,等于把问题从明处挪到暗处,爆发时杀伤力反而更大。
4.4 从一次真实故障看这三点叠加的杀伤力
一个曾经让我印象很深的线上故障,正好把这三点叠加串在了一起。
那是一个积分发放链路:用户在App里完成一笔订单后,订单服务发送一条异步消息,积分服务消费消息后给用户账户增加积分。某天消息队列出现抖动,部分消息消费超时后重试投递。恰好积分服务消费端的幂等又没做到位——重复消息被当成新积分发放,一批用户积分被翻倍计入。发现的时候已经过去两小时,只能通过流水表逐条反查,重算每个用户应得与实际到账的差值,再批量做扣减脚本。整场事故耗时将近一个通宵,而这个通宵本可以在设计阶段用“消息消费时按订单号做幂等唯一约束”一句话就省下来。
做分布式系统设计,关键链路每个环节都要先问自己:消息重复怎么办?请求重试怎么办?数据能对账吗?这三问问完再往下设计,能挡掉大半后期线上事故。
5. 架构评审里那些必须正面回答的细节问题
一个架构方案靠不靠谱,不是听宣讲人讲得顺不顺,而是靠几个直击要害的细节问题去验证。我自己在评审时最爱问下面几类问题,答得模糊的地方,往往就是方案里的潜在敏感点。
5.1 每个核心依赖都要能回答“挂了会怎样”
当一个人设计依赖了缓存、消息队列、第三方支付系统等外部组件时,我会直接追问:如果这个组件现在立刻不可用,系统会发生什么?是局部降级还是全站瘫痪?降级方案是自动触发还是需要人工介入?
有些团队的回答能让我放心——比如“缓存挂了会自动降级直连数据库,数据库扛得住,只是响应时间变长,我们提前做过压测”;但有些回答就让人心里一沉——“这个组件挂了就需要切流量到备集群,人工操作大概十五分钟内能完成。”十五分钟的不可用窗口,在很多业务里已经等同于一场严重事故。备集群、降级开关、熔断阈值,这些细节在做架构设计时就应该明确下来,不能等真出了故障再临场商量。
5.2 数据一致性验证题:同样数据在两个地方存储,以谁为准
如果系统里同一份数据存在多个存储中——比如Elasticsearch里有一份商品信息用于搜索,MySQL里有一份原始商品信息用于交易,那架构评审中一定要能回答:两份数据以谁为准、从哪边发起同步、同步失败怎么办、谁负责补偿。
很多搜索与交易数据不一致的线上事故,根因就是当时没定义清楚“主数据源”。结果运营在后台改了商品价格,搜索引擎里价格还是旧值,用户搜索看到的新价格一点进详情页就变贵,客诉直接爆炸。解决方案通常分两块:一是从源头主数据单向流向从属存储,更新先落主库,再通过消息通知搜索引擎更新;二是建立定的对账任务定期扫描差异,不一致就按主库覆盖从库。主从关系一明确,很多模糊地带会瞬间清晰。
5.3 能不能画清楚核心请求的完整生命周期
评审架构时,我喜欢在白板上随手挑一个核心请求,让方案设计者讲清楚一条链路的完整生命周期:用户触发什么动作、请求经过哪些服务、每个服务做什么处理、数据写到哪个存储、是否发消息、消息有谁消费、失败怎么处理、用户端最终看到什么。
以前带团队做订单系统时,这个“讲一段完整生命周期”的习惯帮我发现过不少设计阶段的隐患:比如有人设计支付回调时,回调处理逻辑能重入但查询接口未做幂等;有人把下单和扣库存放在两个服务里却完全没想清楚扣库存失败后订单状态怎么流转。这些问题如果在白板环节就被发现,代价只是改几行设计;如果上线后再暴露,就是完整的事故处理流程。让团队习惯用“完整链路讲述”来做方案推演,是性价比极高的架构评审手段。
5.4 架构决策记录:为什么当初会这么选,这比画图重要
很多团队的架构文档是一堆“当前长什么样”的图,唯独没有“为什么长这样”的记录。等大半年后有人问起为什么这块数据库用了分库分表而不是用分布式中间件,好几个人给出来的理由都是“当时讨论决定的,具体原因我记不清了”。这种信息丢失会让后续演进失去决策依据,后人要么不敢动前人设计,要么推倒现有方案重来一遍。
所以我的团队里有个硬性习惯:每个架构决策必须同步维护一份简短的ARC(Architecture Decision Record),至少包含:
| 项目 | 内容 |
|---|---|
| 决策背景 | 当时要解决什么问题,有哪些约束条件 |
| 备选方案 | 除当前方案外还考虑过哪些,为什么被否掉 |
| 决策结果 | 最终选了哪个方案,关键细节怎么落地 |
| 预期代价 | 接受这个方案会带来哪些已知弱点 |
| 后续观察点 | 什么时候该重新审视这个决策,哪些信号出现了就说明需要调整 |
写这份文档不费多少时间,却能让团队在半年后重新评估架构时知道当初为什么这么设计、哪些设计当时就是带病上线的、哪些信号触发后需要整体review。没有这些记录,架构演进就只能靠考古式地翻旧代码,效率低且容易误判。
6. 不只是技术:团队结构、商业节奏怎么反向塑造架构
最后这一点很少在纯技术文章里讲,却是我做了这么多年后最想强调的。架构从来不只是技术选择,它同时是组织选择和组织能力的映射。
6.1 康威定律对架构的影响比大多数人想的实在
康威定律说:设计系统的组织,其产生的设计等同于组织内部的沟通结构。这话听着像一句高深的组织行为学格言,但落到现实里非常具体——如果你的团队是两个小组,一个负责前端展示,一个负责后端逻辑,那么系统最终长成前后端分离的架构几乎是必然;如果你的团队按“订单组”、“用户组”、“商品组”划分,那么服务边界大概率会沿着这三个业务域切。反过来也一样,你若期望系统变成微服务架构,却不调整团队结构和沟通方式,强拆出来的微服务最后也会被各种绕过服务边界的直连数据库和共享表重新耦合回去。
架构设计时先看一眼团队结构,能让很多规划落地得更顺。规划的服务边界跟团队分工越一致,代码归属越清晰,后续的维护界面和发布协作越不容易起冲突。等团队规模增长后,再次审视架构与团队的匹配度,该微服务化时自然会水到渠成地演进,不该微服务化的即使在技术上硬推也注定维持不下去。
6.2 业务处在不同阶段,架构的优先级完全不同
一个刚上线还在验证商业模式的业务,和一个已经稳定盈利、正被各种合规要求猛敲的业务,对同样一个技术决策的答案会截然相反。前者第一优先级是快速试错、快速上线,任何拖慢迭代速度的架构设计都要慎重;后者则要把稳定性、可审计性、可回溯性放到最高优先级。
最典型的冲突场景是:业务方说“这个功能下周必须上”,架构师说“这个改动需要重构底层数据模型,建议至少排两周”。这种冲突常常被理解为业务方不懂技术,但往深看,本质是商业节奏要求“快”,架构现状又约束了“快”的上限。有经验的架构师不会一句“改不了”把业务方怼回去,而是会做一个快速的低成本过渡方案——比如先通过兼容层把新功能接上,底层重构并行推进,业务先跑起来,架构再逐步落地。有人说这是技术债,但有时候“带着合理限度的技术债快速进入市场”本身就是正确的架构决策。
6.3 架构设计不是一次性工程,而是持续演进的过程
很多团队把架构设计当成项目启动阶段的“一次性投入”——画完图、做完评审、开始编码,架构活动就算告一段落了。但架构的生命力恰恰在于它需要持续被评估、被调整、被演进。业务在变、团队在变、技术在变,架构作为一个承载所有变化的结构,不可能静止不动。
我现在更愿意把架构演进当成一个持续存在的工程活动,而不是某个里程碑节点的一次性产出。项目上线后,每个季度都会有一个专门的架构review时间,拉上各模块的技术负责人,把现有架构对照最近一段时间的业务变化、技术债务、线上故障、性能瓶颈重新过一遍。要问的核心问题很简单:现在的架构还是最适配当前业务形态的吗?哪里产生了不合理的耦合?哪些地方的技术债快到临界点了?哪些当初的权衡已经因为条件变化而不再成立?这样的复盘不追求每次都有大动作,很多时候结论只是“当前架构仍然合适,有三个小点需要微调”,但这个持续审视的习惯,能防止架构不知不觉地烂掉而不自知。
最后说点实在的
架构设计说到底是选择跟代价打交道的活儿。做选择之前想清楚自己的敏感点在哪、权衡标准是什么,能让很多纠结变得没那么纠结。没有一套架构能同时做到绝对简单、绝对灵活、绝对高性能、绝对省成本,想清楚当下最不能丢的那个指标是什么,然后用一套有纪律的方法去守住它,就是架构师的大部分工作了。
几年实践下来,我给自己总结了一套固定的项目启动路径,也分享在这里:先跟业务方把未来半年到一年的演进节奏聊透,再据此定数据一致性分级和核心链路方案,能简单就绝不复杂、需要预留的趋势方向留好独立扩展点,重要写路径一律设计幂等,选型理由记录成决策文档。这一套做下来架构不敢说有多漂亮,但至少踩坑的密度能降下来不少。架构这行没有标准答案,看的是谁能在不确定里做出适合当下的决定,并且愿意为那个决定的后果长期负责。
