您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center 汽车系统工程   模型库
    学习助手
会员   
   
FDE(前沿部署工程师)实践指南
11月11-12日 北京+线上
OCSMP 认证培训
11月19-20日 北京+线上
AI赋能产品管理实战
12月10-11日 北京+在线
     
   
 订阅
架构是学问,也是艺术
 
作者: 摩方笔记
  8   次浏览      1 次
 2026-11-10
 
编辑推荐:
文章主要介绍了架构设计是在技术学问基础上进行取舍的艺术,并系统梳理了从演进式架构、性能与容量规划、数据存储选型、资源管理、服务拆分、治理监控到稳定性与分布式共识等42条实践法则,希望对你的学习有帮助。
本文来自于剑桥摩方笔记,由火龙果软件Alice编辑、推荐。

服务要不要拆,数据该放哪儿,很少有现成答案。架构设计说到底是在做取舍:眼前最该解决什么,团队和成本又允许走多远。这篇文章聊的,就是做这些判断时需要想清楚的事。

架构是学问,也是艺术。

先说学问。架构师要懂的东西,确实有点杂。

往下,要理解 CPU、硬盘、内存和物理网络;往上,要和操作系统、数据库、应用服务器及各种通信协议打交道。系统一旦变大,缓存、消息队列、服务拆分、分布式一致性和容灾也会接连找上门。再往深处走,还绕不开架构理论、方法论,以及看待复杂系统的方式。

技术懂得多,并不等于方案就能落地。架构师得有主见,又不能听不进意见;要能把问题讲明白,也不能靠漂亮话推动方案。

再说艺术。真实项目很少只有一个正确答案。

拿订单系统来说。有人会从单体起步,有人会提前拆出库存和支付;有人要求数据马上对齐,有人能接受几秒钟的延迟。这些选择都可能成立,区别只在于当时的业务走到了哪一步,团队有多少人,又愿意为复杂度付出多大成本。

所以我一直觉得,架构师有点像厨师。食材和工具都摆在面前,懂多少种烹饪技法当然重要;可真到了灶台前,还得知道这顿饭做给谁吃、预算有多少、几点必须上桌。

顺着一个系统会遇到的问题往下走,看看每一步为什么这样选。

01 架构是设计出来的

很多人第一次做架构,会先打开绘图工具,把网关、缓存、消息队列和微服务一个个摆上去。图很快就画满了,回头再问为什么需要这些东西,却未必答得上来。

法则 1:演进式架构。 多数架构都不是一次画成的。产品早期忙着验证想法,单体或模块化单体往往已经够用。等请求量、数据量和团队规模真的上来了,再逐步引入集群、缓存、异步处理和服务拆分。

“单体 → 集群 → 中台或服务化”只是常见路线,不是每个项目都要走完的升级流程。要不要往下一步走,看的是问题有没有出现,而不是系统已经运行了几年。

法则 2:吸收成熟方法,不照搬流行名词。 DDD、中台化、云原生能流行起来,自然有它们解决的问题。但一种方法再主流,也不能证明它适合眼前这个项目。

具体还得看使用条件。领域驱动设计适合用来梳理复杂业务的模型和边界;业务本来就很简单,先画一套庞大的领域模型,沟通成本可能比收益还高。

做架构时先别急着挑技术。系统为谁服务?现在最痛的问题是什么?有哪些绕不开的约束?失败了要付出什么代价?这几件事没想清楚,后面的选择就没有依据。

02 “三高”到底要高到什么程度

高并发、高可用和高性能经常被放在一起,简称“三高”。可一句“系统要做到三高”,几乎没有提供任何有用信息。

法则 3:高并发要落到请求模型。 一万个缓存读取和一万个复杂事务,给系统的压力完全不同。讨论并发时,至少要说清请求类型、数据规模和峰值会持续多久,还要看看上下游能不能跟得上。

并发量看的是同一时刻有多少请求正在处理,吞吐量看的是单位时间完成了多少工作,例如每秒请求数(QPS)。这两个指标彼此相关,却不能混为一谈。

法则 4:高可用要变成服务目标。 高可用(High Availability,HA)说的是系统能不能持续提供服务。按一年 365 天粗略换算,99.9% 的可用性允许约 8.76 小时不可用;到了 99.99%,只剩 52.56 分钟;99.999% 则大约是 5.26 分钟。

这只是方便理解的时间换算。落到项目里,还要约定统计周期、什么算成功请求、计划维护算不算停机,以及依赖服务出故障时该怎么记。几个“9”也不是越多越好。目标每提高一档,冗余、故障演练和日常运维的投入都会跟着增加。

法则 5:高性能先看延迟、吞吐量和资源效率。 无锁数据结构很容易吸引注意力,可它只解决特定场景里的竞争。慢查询、网络往返、磁盘 I/O、对象分配、锁竞争和垃圾回收,任何一项都有可能拖慢系统。

动手优化前,先把数据量出来。平均延迟经常会掩盖问题,还要看 P95、P99 这样的分位数。P99 表示 99% 的请求延迟不超过这个数值,剩下那 1% 的慢请求也就不容易藏在平均值里。没有测量支撑的优化,常常只是换了一个地方堆复杂度。

03 系统怎样变快,又怎样变大

系统慢了,最容易想到的办法就是加机器。可读请求慢、写请求堵、静态资源占带宽,本来就不是同一个问题,处理方法当然也不同。

法则 6:高并发读,先减少重复工作。 缓存做的事情很直接:算过或查过的结果,尽量别再做一遍。商品详情、配置信息和热点查询都可能因此受益。不过缓存每多一层,失效、穿透、热点 Key 和数据一致性也会多一层麻烦。

法则 7:高并发写,先区分必须同步和可以延后。 用户提交订单后,系统通常要马上确认订单有没有创建成功。发送短信、更新推荐特征这类工作,可以晚一点做,交给消息队列慢慢消化。异步能把高峰摊开,却不会顺手解决失败、重复和消息顺序。

法则 8:静态资源尽量不要压在应用服务器上。 图片、脚本和样式文件可以交给 Nginx、对象存储或内容分发网络(Content Delivery Network,CDN)。应用服务器的 CPU 和连接数,应该尽量留给真正需要业务计算的请求。

这些地方都处理过了,容量还是不够,再来看垂直扩展和水平扩展。

法则 9:垂直扩展先提升单节点能力。 增加 CPU 和内存,换更快的磁盘与网络,或者减少单机内部的 I/O 和锁竞争,都属于垂直扩展(Scale Up)。这种方式改动小,常用来快速缓解压力。它的局限也很明显:单机总有上限,单点故障依然存在。

法则 10:水平扩展要先解决状态和热点。 水平扩展(Scale Out)靠增加节点来分担请求或数据。应用能加实例,缓存能组集群,数据库也能分片。只是机器多了不代表压力自然均匀:会话如果还留在单机内存里,或者大部分流量都集中在少数热点上,新加的节点可能根本帮不上忙。

所以,“一万 QPS 应该用什么架构”没法单独回答。先说清每个请求在做什么、最多能等多久、要处理多少数据,峰值又会持续多长时间,容量规划才有意义。

04 数据该放在哪里

数据库选型最容易被产品名字带跑偏。新手常问“该选 MySQL 还是 Elasticsearch”,其实应该先问:这份数据怎么写、怎么查,写错或丢失后会造成什么后果?

法则 11:高频查询需要合适的索引。 关系型数据库常用 B+ 树做索引,点查和范围查询都比较合适。LSM Tree(Log-Structured Merge-Tree,日志结构合并树)则倾向于先顺序写入,再到后台合并,因此常见于写入压力较大的存储系统。

不过,不能据此得出“写多就选 LSM,读多就选 B+ 树”。写放大和读放大有多严重,压缩与缓存怎么做,最后都取决于具体实现和实际负载。

法则 12:事务性数据优先选择能提供所需事务能力的存储。 创建订单、扣减账户余额,往往要求一组操作要么全部成功,要么全部失败,还要处理并发读写和故障恢复。这就是常说的原子性、一致性、隔离性和持久性,也就是 ACID。关系型数据库很常见,但选定产品之后,隔离级别和并发冲突仍然要自己设计。

法则 13:数据天然以文档聚合时,可以考虑文档型或其他 NoSQL 存储。 仅仅因为数据“非结构化”,还不足以决定使用 NoSQL。还要看结构是否经常变化,查询是不是主要围绕一个聚合展开,事务会跨过哪些边界。文档数据库也有事务能力,只是它的数据模型、事务成本和扩展方式与关系型数据库不同。

法则 14:文件、图片、音视频交给对象存储。 这些大对象通常不适合直接塞进业务数据库。数据库保存文件标识、业务关系和权限,真正的文件内容交给 MinIO 或云对象存储,后续扩容和分发会省事得多。

法则 15:全文检索使用搜索索引,但要明确事实来源。 Elasticsearch 这类搜索系统擅长全文检索和相关性排序,却不适合取代订单的事实库。订单仍然保存在事务数据库中,需要搜索的字段再同步到索引。同步难免有延迟,补偿、对账和索引重建都要提前考虑。

法则 16:海量结构化数据先解决访问路径,再考虑分库分表。 数据到了亿级、百亿级,也不等于马上就要水平拆分。先看冷热数据怎么分、查询通常扫多大范围、多久可以归档,有没有明显热点。弄清这些,再决定做分区、分片,还是引入分析型系统。拆分之后的跨分片查询、事务和扩容,都要付出额外成本。

法则 17:节点和关系是主要查询对象时,考虑图数据库。 数据血缘、社交关系和知识图谱经常要沿着节点和边一层层查下去,图数据库能直接表达这种关系。可如果只是几次简单关联,为此多维护一套 Neo4j,未必划算。

法则 18:按时间持续写入和聚合时,考虑时序数据库。 监控指标和物联网数据天然带着时间标签,也经常按时间窗口写入、压缩和聚合。InfluxDB、TimescaleDB、OpenTSDB 各有侧重,最终还得看自己的数据模型、查询习惯和运维环境。

一个系统同时使用几种存储并不稀奇,也不是为了显得架构先进。事务数据库保存交易事实,搜索引擎负责检索,对象存储保存文件。各做各擅长的事,往往比强迫一种数据库包办所有需求更稳妥。

05 资源什么时候准备,能不能反复使用

算法当然会影响性能,资源什么时候创建、请求能不能合在一起处理,同样重要。

法则 19:队列缓冲与批处理适合摊薄固定成本。 多次小写入合成一个批次,可以少跑几趟网络,也能减少提交次数。代价是系统要等数据凑成一批,延迟自然会上升。生产速度长期快于消费速度,队列还会越积越多,所以容量上限和背压不能缺席。

法则 20:预加载用启动成本换运行时速度。 系统启动时先加载热点配置、建立必要连接,第一次请求就不用临时准备。启动会更慢,资源也可能先占着不用,这就是交换条件。

法则 21:懒加载用首次延迟换更少的启动工作。 有些资源很少用到,或者一次可能创建很多,等真正访问时再初始化更合适。预加载还是懒加载,主要看创建成本、使用概率,以及能不能接受第一次访问稍慢一点。

法则 22:内存池减少频繁申请和释放内存。 Netty 等高性能网络框架会重复使用内存块,省下频繁分配的成本,也有机会降低碎片风险。池化并不是白来的,管理更复杂,配置不合适还可能长期占住大量内存。

法则 23:池化要先说明复用什么、限制什么。 对象池复用的是创建和销毁成本较高的对象。连接池除了复用连接,还在控制有多少压力能同时打到下游;线程池管的则是工作线程和任务并发。普通小对象创建得很快,硬塞进池里,可能只会多出同步和归还的成本。

池调大了,下游能力不会跟着凭空增长。把数据库连接池从 50 改成 500,数据库未必能多处理十倍请求,更可能发生的是 500 个请求一起冲过去。

06 服务到底该怎么拆

说到微服务,人们很容易把“拆得细”和“架构先进”画上等号。代码切开并不难,难的是找到真正能够独立变化的业务边界。

法则 24:单一职责不等于一个服务只做一张表。 服务应该围绕一项相对完整的业务能力来设计。订单服务同时处理订单创建、状态流转和取消规则并没有问题,因为这些工作都属于订单这个业务边界。

法则 25:松耦合要落实到接口和数据所有权。 服务之间既可以调用同步 API,也可以靠事件协作。无论选哪一种,契约都得清楚。别的服务更不能绕过接口,直接改动不属于自己的数据。

独立拥有数据,也不代表每个服务从第一天起就要独占一套物理数据库。先把写入入口和变更责任管住。要不要真的拆库,再看隔离、容量和运维成本。

法则 26:先识别领域,再决定服务。 领域驱动设计(Domain-Driven Design,DDD)从业务概念、规则和限界上下文出发。订单、库存、支付、履约该不该拆开,先看它们的业务含义和变化边界。按页面或数据库表直接切,通常切不出可靠的服务边界。

法则 27:分层是为了保护业务规则。 常见的分层有接口层、应用层、领域层和基础设施层。接口层接收请求,应用层编排用例,领域层放核心业务规则;数据库、消息和外部系统的具体接入,则留给基础设施层。

层与层之间最值得关注的是依赖方向。领域层当然可以有业务逻辑,只是不要反过来依赖某个数据库、Web 框架或消息中间件。将来替换基础设施时,业务模型才不至于跟着推倒重写。

07 拆开之后,怎样看得见、发得出、管得住

单体里一次普通的函数调用,服务拆开后就变成了网络请求。独立部署和扩展是好处,调用定位、版本发布和运行治理则是随之而来的成本。

服务实例会扩容、缩容,调用地址也会变化。调用方得知道服务现在在哪里、哪些实例还能用,请求该发给谁。配置更新、灰度发布和依赖故障,也没法继续靠人逐台处理机器。

服务治理就是来收拾这些问题的。服务注册与发现负责找到实例,负载均衡和路由决定流量往哪儿走,配置管理与灰度发布控制系统怎样变化。指标、日志和链路追踪把运行结果反馈回来,团队才能知道调用是否正常、规则有没有生效。至于超时、重试、限流、熔断和隔离,下一节再细说。

法则 28:监控与记录要在上线前设计。 指标告诉我们系统有没有异常,日志记录某个节点发生了什么,链路追踪则还原一次请求经过了哪些服务、时间花在了哪里。三类信息最好用统一的请求标识串起来,否则出了问题还是各查各的。

法则 29:开发运维一体化要让发布过程可重复。 持续集成与持续交付(CI/CD)的价值很实际:同一个版本,每次都用相同的方式检查、测试、构建、部署和回滚。流水线看起来多复杂,并不是重点。

如果一个微服务不能独立测试、独立发布,那它很可能只是被放到了网络另一端。复杂度增加了,独立演进的好处却没有拿到。

法则 30:API 网关适合承接统一的入口能力。 路由、认证、限流和灰度发布这类入口能力,可以集中放在网关。业务规则就别继续往里塞了,否则网关很快会变成新的性能瓶颈和故障中心。

认证可以由网关统一处理,具体能不能操作某项业务资源,仍然要由服务自己判断。密钥怎么保存、敏感数据怎么保护、哪些操作需要留审计记录,也应该在设计时说清楚。等上线后再补,通常已经晚了。

法则 31:实时推送先分清单向还是双向。 WebSocket 建立连接后,客户端和服务端都能主动发消息,适合聊天、协作编辑和在线游戏。服务器发送事件(Server-Sent Events,SSE)走的是另一条路:服务器通过 HTTP 持续向浏览器发送 UTF-8 文本事件,方向只有服务端到客户端。浏览器的 EventSource 还带有自动重连和事件编号机制。

如果页面主要接收 AI 流式输出、任务进度或实时通知,偶尔才通过普通 HTTP 提交操作,SSE 往往更省事。客户端和服务端都要频繁发消息,或者消息里包含二进制数据,再考虑 WebSocket。

关注点 SSE WebSocket
通信方向 服务端到客户端 客户端与服务端双向
数据形式 UTF-8 文本事件 文本或二进制消息
浏览器支持方式 EventSource ,内置重连机制 WebSocket ,重连通常由应用处理
常见场景 AI 流式输出、任务进度、通知 聊天、协作编辑、实时游戏

长连接建起来,事情才刚开始。部署时要检查网关和反向代理会不会缓冲响应、多久会关掉空闲连接,还要估算连接数量和消息频率,处理好心跳、背压与断线恢复。Netty 可以构建 WebSocket 服务,但“单节点支持一百万连接”离开测试条件就没有意义。操作系统配置、内存、消息频率、业务处理、加密和网络带宽,都会改变结果。能把连接建起来,也不代表能稳定处理同样规模的活跃消息。

08 系统出故障时,怎样不被一起拖垮

系统一定会出错。硬件会坏,网络会抖,程序有缺陷,人也可能误操作。稳定性设计关心的,是出错之后能不能尽快发现,影响会不会继续扩大,最后又该怎样恢复。

法则 32:冗余要配合自动故障转移。 多部署一个副本,只能说明手里有备用。健康检查能不能发现故障,流量能不能绕开异常节点,客户端能不能连到新的节点,才决定这份备用是否真的有用。

法则 33:数据容错关注错误怎样被发现和限制。 校验、冗余编码和 RAID 可以发现或承受一部分硬件与数据错误,但它们各自防护的故障并不相同。尤其要记住,RAID 不是备份。

法则 34:数据容灾关注严重故障后怎样恢复。 远程备份、快照和跨地域复制,用来应对误删、存储损坏乃至整个站点不可用。方案里还要写清恢复点目标(Recovery Point Objective,RPO)和恢复时间目标(Recovery Time Objective,RTO)。备份有没有用,不能看任务状态显示成功,要靠恢复演练验证。

法则 35:心跳只是故障判断的一个信号。 节点定期发送或响应心跳,可以帮助判断它还活着没有。心跳失败,有时只是网络拥塞;进程还在,也可能已经处理不了请求。实际判断通常还要结合超时、健康检查和一套明确的故障判定策略。

远程调用都应该设置超时。碰上可以恢复的临时错误,可以重试,但次数要有限,并配合退避和随机抖动,别让一批请求同时回来制造新的高峰。重试前还得确认操作是否幂等。支付请求超时,不代表下游没有扣款;缺少业务唯一键或幂等令牌,一次网络故障就可能变成两次扣款。

法则 36:限流是在容量边界前控制入口。 系统稳定时每秒只能处理 2,000 个请求,却一下放进来 10,000 个,线程、连接和队列很可能一起耗尽。限流是为了在过载时保住一部分服务能力。至于被挡住的请求是提示用户、进入队列还是走降级,也要由业务来决定。

法则 37:熔断让异常依赖暂时退出调用链。 当失败率或慢调用超过阈值,熔断器会直接挡住后续请求,不再让它们继续苦等。过一段时间,再放少量流量进去试探。所谓关闭、打开和半开,说的就是这几个阶段。

法则 38:隔离限制一个故障最多占用多少资源。 不同调用使用各自的线程池、连接池或实例,可以防止某个慢依赖把全部资源拖住。熔断决定还要不要继续调用,隔离则划定它最多能占用多少资源。

09 多节点之间怎样找到数据、交换状态

系统从一台机器扩展到多台,马上会碰到两个问题:数据究竟在哪个节点,节点之间又怎样发现彼此、交换状态。

法则 39:一致性哈希用于降低节点变化时的数据迁移范围。 它先把键映射到一个哈希环,再沿着环找到负责的节点。新增或移除节点时,通常只有环上的部分数据需要搬家。虚拟节点能让分布更均匀,却解决不了所有问题,热点 Key、数据倾斜和跨分片查询还得单独处理。

范围分片适合区间查询,最新写入却可能集中成热点。取模分片容易理解,节点数量一变,往往要迁移大量数据。一致性哈希减少了迁移范围,也有自己的限制。分片算法没有通吃的那一种。

法则 40:Gossip 适合去中心化地传播成员和状态信息。 每个节点定期把自己知道的消息告诉其他节点,信息就这样一点点传遍集群。它适合成员发现和状态传播,但扩散需要时间,也不能拿来保证关键写入的强一致。

10 多节点意见不一致时,系统该听谁的

CAP 大概是最容易被背成口号的分布式理论之一。可真要拿它分析系统,边界比口号重要得多。

法则 41:CAP 讨论的是网络分区发生时的选择。 C 是一致性(Consistency),A 是可用性(Availability),P 是分区容错性(Partition Tolerance)。这里说的可用,不等于每个业务操作都必须成功,而是到达非故障节点的请求最终能得到响应。网络分区出现后,坚持让所有节点都返回同一份最新结果,就可能要拒绝或等待一部分请求;让系统继续响应,则可能读到尚未同步的旧数据。

这不是给整个系统贴一个永久的 AP 或 CP 标签。同一个系统里,账户余额更看重一致性,商品推荐则可以先返回可用结果。数据不同,操作不同,选择也可以不同。

法则 42:最终一致性允许副本短暂不同,但最后要能收敛。 商品浏览量、搜索索引和部分推荐数据,通常能接受几秒钟的延迟。账户余额、库存扣减和订单状态就不同了,一旦出错,代价高得多,设计时也要更谨慎。

选择最终一致性,并不代表可以不管一致性。信息怎样传播,冲突怎么处理,失败以后如何补偿,多久应该重新对齐,都要写清楚。业务到底能容忍多长的不一致窗口,才是做选择的依据。

11 结语:法则是地图,不是答案

写到这里,清单已经很长了。硬件、网络、存储、微服务、稳定性和分布式系统,随便挑一项都还能继续往下讲。

真正做方案时,却不能把清单上的技术全堆进去。

学问让我们知道手里有哪些工具,它们各自能解决什么问题。我理解的“艺术”,就在接下来的取舍里:眼下最该解决什么,团队能承受多少复杂度,哪些风险必须现在处理,哪些可以等业务真的走到那一步再说。

   
8   次浏览       1 次
相关文章

企业架构、TOGAF与ArchiMate概览
架构师之路-如何做好业务建模?
大型网站电商网站架构案例和技术架构的示例
完整的Archimate视点指南(包括示例)
相关文档

数据中台技术架构方法论与实践
适用ArchiMate、EA 和 iSpace进行企业架构建模
Zachman企业架构框架简介
企业架构让SOA落地
相关课程

云平台与微服务架构设计
中台战略、中台建设与数字商业
亿级用户高并发、高可用系统架构
高可用分布式架构设计与实践

最新活动计划
AI时代的需求分析师培养 11-4[北京]
MBSE(基于模型的系统工程) 11-11[北京]
FDE(前沿部署工程师)实践 11-12[北京]
OCSMP 认证培训 11-19[在线]
UAF架构体系与实践 11-24[北京]
AI赋能产品管理实战 12-10[在线]
国产化数据库设计&优化 12-24[北京]
 
 
最新文章
架构设计-谈谈架构
实现SaaS(软件及服务)架构三大技术挑战
到底什么是数据中台?
响应式架构简介
业务架构、应用架构与云基础架构
最新课程
软件架构设计方法、案例与实践
从大型电商架构演进看互联网高可用架构设计
大型互联网高可用架构设计实践
企业架构师 (TOGAF官方认证)
嵌入式软件架构设计—高级实践
更多...   
成功案例
某新能源电力企业 软件架构设计方法、案例与实践
中航工业某研究所 嵌入式软件开发指南
某轨道交通行业 嵌入式软件高级设计实践
北京 航天科工某子公司 软件测试架构师
北京某领先数字地图 架构师(设计案例)
更多...