本文档使用AI工具将原始的手工笔记进行了整合, 并由AI进行评审后统一修正、重组与补全。
本文档整合 12 份原始设计原则材料,修正错误并补充现代架构要点。遵循"精简为主,难点注解"原则。
1. 基础理论
1.1 CAP 定理
分布式系统最多同时满足以下两项:
| 特性 | 含义 |
|---|---|
| Consistency(一致性) | 所有节点同一时刻看到相同数据 |
| Availability(可用性) | 每个请求都能收到响应(不保证数据最新) |
| Partition Tolerance(分区容错) | 网络分区时系统仍能运行 |
注解:网络分区(P)在分布式系统中必然发生(网络不可靠),所以实际是在 C 和 A 之间做选择。微服务通常选 AP + 最终一致性(如电商订单),金融核心系统可能选 CP(如银行转账)。
1.2 BASE 理论
CAP 的延伸,强调基本可用、软状态、最终一致:
- BAsically Available:系统出现故障时允许损失部分可用性(如降级为只读)
- Soft state:允许数据存在中间状态
- Eventually consistent:不保证实时一致,但最终会一致
1.3 PACELC 定理
CAP 的扩展,强调**延迟(Latency)**的权衡:
如果存在分区(P),在可用性(A)和一致性(C)之间选择;
否则(E,即正常运行),在延迟(L)和一致性(C)之间选择。
注解:例如 DynamoDB 选 PA/EL(分区时保可用,正常时保低延迟),MongoDB 选 PC/EC(分区时保一致,正常时也保一致)。
1.4 康威定律(Conway’s Law)
“设计系统的组织,其产生的设计等同于组织之内、组织之间的沟通结构。”
实践意义:团队结构决定系统架构。微服务团队应为"两个披萨团队"(6~10 人),每个团队端到端负责一个服务。
2. 12-Factor App
原始材料对 12-Factor 的翻译偏口语化,以下用精简技术语言重述。
| 原则 | 核心要求 | 实践 |
|---|---|---|
| 代码库 | 一份代码库,多份部署 | Git 单仓库,通过分支/标签区分环境 |
| 依赖 | 显式声明依赖 | package.json、pom.xml、go.mod,禁止隐式依赖系统包 |
| 配置 | 配置与代码分离 | 环境变量、配置中心(Nacos/Consul/ConfigMap),禁止硬编码 |
| 后端服务 | 将数据库/缓存等视为附加资源 | 通过 URL 连接,可随时替换(如 MySQL → PostgreSQL) |
| 构建-发布-运行 | 严格分离三个阶段 | 构建(CI 产出制品)→ 发布(绑定配置)→ 运行(启动进程) |
| 进程 | 以一个或多个无状态进程运行应用 | 状态外置(Redis/DB),实例可任意启停和替换 |
| 端口绑定 | 通过端口暴露服务 | 自包含 HTTP 服务,不依赖外部 Web 服务器 |
| 并发 | 通过进程模型扩展 | 水平扩展(加实例)而非垂直扩展(升配置) |
| 易处理 | 快速启动、优雅终止 | 启动 < 5s,SIGTERM 时完成当前请求再退出 |
| 开发/生产等价 | 环境尽量一致 | Docker 容器化,避免"在我机器上能跑" |
| 日志 | 日志作为事件流 | 输出到 stdout,由外部系统(ELK/Loki)收集,应用不管理日志文件 |
| 管理进程 | 后台管理任务作为一次性进程运行 | 数据迁移、报表生成等通过独立 Job 执行 |
注解:12-Factor 诞生于 2012 年 Heroku 时代,核心思想至今有效。现代演进为 15-Factor(补充 API 优先、遥测、认证授权),但 12 条仍是基础。
3. 核心设计原则
原始材料提炼为四字诀:
| 原则 | 含义 | 实践 |
|---|---|---|
| 缓存 | 复用数据,减少重复计算 | CDN、Redis、本地缓存、浏览器缓存 |
| 异步 | 避免阻塞,提升吞吐 | 消息队列、事件驱动、回调网关 |
| 前置 | 提前准备,缩短响应路径 | CDN 预热、边缘计算、数据预加载 |
| 拆分 | 减少复杂度,隔离故障 | 微服务、DDD 限界上下文、读写分离 |
4. 系统分层设计
为什么要分层?
当组织节点较多时调用关系和逻辑愈发复杂,好的分层设计可以带来以下好处:
- 复用代码,
- 解耦合
- 屏蔽细节
分层带来的问题:
- 请求处理时间可能会增加
- 运维复杂性增加
4.1 物理分层(请求流向)
|
|
4.2 逻辑分层
| 层级 | 职责 | 示例 |
|---|---|---|
| 视图层 | 用户可见的界面 | Web 页面、App UI |
| 网关层 | 路由、鉴权、限流 | Spring Cloud Gateway、Kong、Envoy |
| 前端业务层 | 校验、数据准备 | 参数校验、DTO 组装 |
| 核心业务层 | 主业务逻辑 | 订单创建、支付处理 |
| 基础业务层 | 通用后台功能 | 用户中心、支付中心、文件服务 |
| 基础数据层 | 数据访问抽象 | ORM、数据库中间件、缓存中间件 |
注解:分层的本质是数据的移动——同一数据在不同层以最优形式展现。代价是请求链路变长、运维复杂度增加。分层不是越多越好,通常 3~4 层足够。
4.3 小前台、大中台
- 小前台:前端系统尽量小,要求快速迭代和灵活响应业务
- 大中台:将身份认证、交易、支付、消息等通用能力服务化,供多个前台复用
注解:中台不是技术中台一个概念,还包括业务中台、数据中台、算法中台。中台建设最大的坑是"为了中台而中台"——先有小前台的真实复用需求,再沉淀中台能力,而非先建中台再找场景。
4.4 前后端分离
| 分离前 | 分离后 |
|---|---|
| 后端渲染 HTML | 后端提供 API(JSON/XML),前端独立渲染 |
| 前端小改动需后端配合发布 | 前后端独立部署、独立迭代 |
代价:SEO 不友好(SPA 需 SSR 解决)、沟通成本增加、团队技能要求分化。
4.5 其它分层
数据服务层: 对不同业务单元的数据提供统一的访问形式
- 屏蔽多种业务的数据库和缓存等逻辑
- 提供统一的 API 接口,上层业务无需关注分库分表等细节
5. 服务化与微服务
5.1 服务化抽象方向
| 抽象对象 | 服务化后 | 收益 |
|---|---|---|
| 数据库访问 | 数据访问服务(DAS) | 屏蔽分库分表、缓存同步逻辑 |
| 缓存 | 缓存服务 | 统一缓存策略,替换组件(如 Memcached → Redis)不影响上层 |
| 用户数据 | 用户中心 | 统一用户画像、认证授权 |
5.2 服务化核心能力
- 注册发现:服务自注册到注册中心(Nacos/Consul/etcd),调用方动态发现
- 容错路由:熔断、限流、降级、重试
- 本地短路:部分服务优先本地调用(同机部署)以减少网络开销
- 调用方式:同步、异步、并行调用按需选择
- 故障隔离:核心/非核心服务分开部署,单服务故障不扩散
- 屏蔽细节:屏蔽底层实现细节,只暴露必要的业务 API
5.3 高可靠性设计
- 无状态设计:状态外置(Redis/DB),实例可任意替换
- 注册中心集群:即使注册中心宕机,已缓存的服务列表仍可继续运行
- API 网关屏蔽故障节点:健康检查自动剔除异常实例
- 跨机房路由:异地多活,就近访问
6. 依赖与耦合管理
6.1 反向依赖问题
问题:业务 A 变动,需要 B/C/D/F 配合修改。
| 场景 | 问题 | 解法 |
|---|---|---|
| 下游 IP 变更 | 上游硬编码 IP,需改配置重启 | 使用内网域名 + DNS,应用层具备重连机制 |
| 下游扩容 | 上游需同步调整连接池 | 引入注册中心或负载均衡器,上游无感知 |
| 公共库耦合 | 非共性功能沉淀在公共库 | 非共性上移;公共库改造为服务层,保持接口兼容 |
6.2 服务发现演进
|
|
| 方案 | 优点 | 缺点 |
|---|---|---|
| 域名 + DNS | IP 变动无需改应用 | DNS 缓存更新慢(TTL),长连接不自动切换 |
| 注册中心 | 实时感知服务变化 | 引入新组件,需考虑自身高可用 |
| K8s Service DNS | 云原生原生支持 | 绑定 K8s 生态 |
| 网关负载均衡 | 集中管理路由 | 额外引入组件,需考虑自身高可用 |
注解:DNS 缓存是服务发现中最容易被忽视的问题。Linux 默认
nscd缓存 5 分钟,JVM 缓存更久。生产环境建议 DNS TTL 设 10~30 秒,或应用层主动刷新。
7. 高可用设计
7.1 单点类型与消除
| 单点类型 | 示例 | 消除方案 |
|---|---|---|
| 入口型 | Nginx、负载均衡器 | 多节点 + Keepalived/VRRP 虚拟 IP |
| 存储型 | 数据库、SFTP | 主从复制、多副本、分布式存储 |
| 逻辑型 | 定时任务调度器 | 分布式锁(Redis/ZooKeeper)选举主节点 |
注解:主备方案资源利用率仅 50%,现代架构倾向 多活(Active-Active)——所有节点同时提供服务,故障时流量自动切换,利用率接近 100%。
7.2 高可用机制
| 机制 | 原理 | 适用 |
|---|---|---|
| 副本机制 | 数据多份存储,一主多从 | 数据库、消息队列 |
| Leader 选举 | 主节点故障时自动选举新主 | Redis Sentinel、Kafka Controller、etcd |
| 纠删码(Erasure Coding) | 将数据分片编码存储,部分丢失可重建 | 对象存储(HDFS、Ceph、MinIO),节省存储成本 |
注解:纠删码 vs 副本的权衡——3 副本存储开销 200%,纠删码(如 4+2)开销 50%,但纠删码计算开销大、恢复慢。热数据用副本,冷数据用纠删码。
7.3 断路器(Circuit Breaker)
当外部接口大面积错误时:
- 限流降级:减少请求量,只保留核心请求
- 熔断断开:直接拒绝请求,1~3 分钟后探测恢复
- 快速失败:设置超时,避免长时间阻塞
注解:断路器三态——关闭(正常)→ 打开(熔断)→ 半开(探测)。半开状态放少量请求试探,成功则关闭,失败继续保持打开。Hystrix 已停止开发,现代用 Resilience4j(Java)或 Sentinel(阿里,功能更丰富)。
8. 容量与性能设计
8.1 容量评估四步法
| 步骤 | 方法 | 注意 |
|---|---|---|
| 1. 总访问量 | 业务方预估上线后总用户量 | 考虑交易特性(如电商大促) |
| 2. 平均 QPS | 总量 ÷ 总时间 | 按白天 12 小时 ≈ 4 万秒计算 |
| 3. 高峰 QPS | 根据历史曲线或业务特征预估 | 秒杀场景峰值可能是均值 10~100 倍 |
| 4. 单机极限 | 压测得出单机最大 QPS | 分层较多时先找到瓶颈层 |
最终资源 = 高峰 QPS ÷ 单机极限 QPS × 冗余系数(通常 1.5~2)
8.2 架构分离范式
| 分离方式 | 目的 | 实践 |
|---|---|---|
| 动静分离 | 静态资源走 CDN,动态请求走源站 | 页面/JS/CSS/图片/视频 上 CDN |
| 读写分离 | 线性提升读性能 | 主库写、从库读,配合延迟监控 |
| 前后台分离 | 用户侧与运营侧解耦 | 前台保低延迟,后台容忍高延迟 |
注解:动态页面静态化(如新闻首页、商城首页提前生成 HTML)是动静分离的进阶——数据量不大、更新频率低的页面,定时任务生成静态页,用户直接访问 CDN 上的 HTML,源站压力趋近于零。
9. 扩展性设计
9.1 何时需要扩展
- 业务量增 10~100 倍,数据量增数十 TB
- 延迟要求更低,响应速度要求更快
- 云化/容器化、新增数据中心
- 引入新组件(大数据、AI)、接入公共服务(SSO)
- 安全要求提升(双活多活、风控)
9.2 扩展性设计要点
- 不要过度设计:先满足当前 1~2 年需求,预留扩展接口
- 功能开关(Feature Toggle):新功能通过开关控制,随时回退
- 无状态化:状态外置,扩容只需加实例
- 水平扩展优先:加机器 > 升配置
- 接口兼容:向后兼容,支持灰度升级
- 故障隔离:单组件故障不扩散,可独立降级
- 成本控制:避免资源浪费,成本控制在可接受范围内
10. 现代架构设计要点(补充)
原始材料缺少以下现代架构核心内容,补充如下:
10.1 云原生(Cloud Native)
| 要素 | 含义 | 技术 |
|---|---|---|
| 容器化 | 应用打包为容器镜像,环境一致 | Docker、containerd |
| 编排 | 自动化部署、扩缩容、自愈 | Kubernetes |
| 微服务 | 服务独立部署、独立扩展 | Spring Cloud、Dubbo、gRPC |
| 服务网格 | 基础设施层处理服务间通信 | Istio、Linkerd |
| 声明式 API | 描述期望状态,系统自动达成 | K8s YAML、Terraform |
注解:云原生的核心不是"用 K8s",而是不可变基础设施——服务器只读,任何变更通过重新部署实现,杜绝" snowflake server “(手工配置、无法复现的服务器)。
10.2 可观测性(Observability)
三大支柱 + 一个基础:
| 支柱 | 内容 | 工具 |
|---|---|---|
| Metrics(指标) | 聚合数值,看趋势 | Prometheus + Grafana |
| Logging(日志) | 离散事件,查细节 | ELK / Loki / Fluentd |
| Tracing(追踪) | 请求链路,定位慢点 | Jaeger / SkyWalking / Zipkin |
| Profiling(剖析) | 代码级性能分析 | Pyroscope / Parca / Arthas |
注解:可观测性 ≠ 监控。监控是"我知道问题在哪,设个告警”;可观测性是"我不知道问题在哪,通过数据探索发现"。现代架构要求OpenTelemetry 统一标准,避免各系统数据孤岛。
10.3 安全设计(Security by Design)
| 原则 | 实践 |
|---|---|
| 零信任(Zero Trust) | 默认不信任任何请求,内外网一视同仁,全部认证授权 |
| 最小权限 | 服务只拥有完成工作所需的最小权限 |
| 安全左移 | 安全扫描前置到 CI 阶段(SAST/DAST/依赖扫描) |
| Secrets 管理 | 密码/密钥不硬编码,用 Vault / K8s Secret / 云 KMS |
| mTLS | 服务间通信双向 TLS 加密(Istio/Linkerd 自动实现) |
10.4 数据架构设计
| 模式 | 适用场景 |
|---|---|
| CQRS | 读写模型分离,读模型独立优化(ES/Redis) |
| Event Sourcing | 审计要求高、需回放历史的场景 |
| Saga | 长事务分布式场景,通过补偿回滚 |
| Outbox | 保证数据库写入和消息发送原子性 |
10.5 SRE 与可靠性工程
| 概念 | 含义 |
|---|---|
| SLI | 服务质量指标(如延迟 P99 < 200ms) |
| SLO | 服务质量目标(如可用性 99.99%) |
| SLA | 服务等级协议(违约赔偿条款) |
| Error Budget | 允许的错误配额,用完则暂停发布 |
| Chaos Engineering | 故意注入故障,验证系统恢复能力 |
10.6 FinOps(云成本优化)
- 资源标签化,按团队/项目追踪成本
- 自动伸缩(HPA/VPA/Cluster Autoscaler)避免过度预留
- Spot/Preemptible 实例用于非关键负载
- 存储分层(热数据 SSD、温数据 HDD、冷数据对象存储)
11. 架构设计 Checklist
业务功能
- 需求理解 → 领域建模(DDD) → 数据结构设计
- 选择合适的技术栈(语言、框架、数据库)
非业务功能
- 安全性:防攻击、密码安全、传输加密、访问控制
- 稳定性:防崩溃、故障隔离、风险承受能力评估
- 高性能:响应时间、吞吐量、资源利用率
- 灵活性:敏捷性(快速引入/淘汰组件)、弹性(平滑扩缩容)
- 可维护性:自动化部署、故障自愈、减少人工介入
- 成本:物理成本、建设成本、维护成本、人员成本
- 易用性:运营人员能否通过系统产出决策
- 生命周期:满足上线时间、运行周期、平稳下线
- 外部依赖:外部系统支撑能力弱时,是否有冗余/容错设计
架构验证
- 是否遵循 12-Factor / 云原生原则
- 是否消除单点故障
- 容量评估是否覆盖峰值(含秒杀场景)
- 是否具备熔断、限流、降级能力
- 是否具备可观测性(Metrics/Logging/Tracing)
- 是否设计功能开关,支持灰度发布
- 安全扫描是否集成到 CI 流水线
- 是否具备混沌工程演练能力
文档版本:v2.0
整合说明:基于 12 份原始设计原则材料整合,修正了"频闭"等错别字、编号重复等问题,补充了 CAP/BASE/PACELC、云原生、可观测性、零信任安全、SRE、FinOps、CQRS/Event Sourcing/Saga 等现代架构设计要点。