1. 单体架构(Monolith)

定义:将应用的所有功能(前端、后端、数据处理、定时任务等)打包成一个单一的可部署单元(如一个 WAR 包、一个可执行 JAR、一个 Flask/Django 项目)。

特点
- 单一代码库:所有模块代码放在一起。
- 单一部署单元:整个应用作为一个进程运行。
- 共享数据库:所有模块使用同一个数据库。

优点
- 开发初期简单,易于调试和测试。
- 部署单一,运维成本低(只需管理一个服务)。
- 跨模块调用是进程内调用,性能高、无网络延迟。

缺点
- 代码耦合:随着功能增加,代码变得复杂、难以维护。一处改动可能影响全局。
- 扩展瓶颈:只能整体水平复制(克隆整个应用),无法针对性能热点单独扩展。
- 技术锁定:很难在某个模块使用不同的技术栈。
- 部署影响:任何微小修改都需要重新部署整个应用。

典型场景:创业初期、小型内部系统、简单 CRUD 应用。


2. 前后端分离

定义:将前端(用户界面)和后端(业务逻辑、数据存取)分成两个独立的项目,通过 API 接口通信。

架构图

[浏览器/移动端] --(HTTP/HTTPS)--> [后端 API 服务(REST/GraphQL)] --(ORM)--> [数据库]
                ^
                | 返回 JSON/XML

核心特点
- 前端:独立项目,通常使用 React、Vue、Angular 等框架,负责 UI 渲染和用户交互。
- 后端:只提供 API 接口(JSON/XML),不关心页面展示。
- 通信:无状态(通常使用 JWT 或 Session + 跨域 CORS)。

优点
- 独立开发部署:前后端团队可以并行工作,独立版本迭代。
- 技术栈解耦:前端可以随意选择框架(React/Vue),后端可以选择最适合的语言(Python/Go/Java)。
- 多端复用:同一套后端 API 可同时服务 Web、移动 App、小程序、第三方客户端。
- 性能优化:前后端可以分别针对瓶颈优化(如前端做静态 CDN,后端做缓存)。

缺点
- 增加沟通成本(API 契约定义、版本管理)。
- 首屏加载可能变慢(需额外请求数据),但可通过 SSR(服务端渲染)缓解。
- 对 SEO 不友好(纯 SPA 需预渲染)。

与单体架构的关系:前后端分离并不等于非单体。即使前后端代码分离部署,后端本身仍然可以是单体架构。


3. 微服务

定义:将单一应用程序划分为一组小型的、独立的服务。每个服务围绕业务能力构建,可独立开发、部署、扩展,使用轻量级通信机制(通常是 HTTP REST 或 gRPC)。

核心原则
- 按业务边界拆分:例如订单服务、用户服务、商品服务、支付服务。
- 每个服务拥有自己的数据库:避免数据库层面的强耦合。
- 去中心化治理:每个服务可选用不同的技术栈。
- 基础设施自动化:需要服务发现、负载均衡、容错(熔断、重试)、分布式追踪等。

优点
- 独立部署与扩展:修改某个服务只需重新部署该服务,且可针对高负载服务单独扩容。
- 故障隔离:某个服务崩溃不会导致整个系统瘫痪(但需要设计降级)。
- 技术多样性:新服务可以使用更适合的语言或框架。
- 团队自主:小团队可以拥有完整的服务生命周期。

缺点
- 分布式系统复杂度:网络延迟、数据一致性(分布式事务)、服务发现、链路追踪等挑战。
- 运维成本高:需要容器编排(Kubernetes)、监控、日志聚合、API 网关等基础设施。
- 数据一致性难:跨服务的事务通常采用最终一致性(如 Saga 模式),而不是传统 ACID。
- 接口版本管理:服务间依赖升级困难。

何时适用:大型复杂系统、多个独立团队协作、需要频繁独立发布、弹性扩展需求高的场景。对于中小型项目,单体或模块化单体可能更合适。

与前后端分离的关系:前后端分离是用户界面与业务逻辑的解耦;微服务是后端内部的进一步拆分。两者可共存:前端调用 API 网关,网关路由到不同的微服务。


4. 消息队列

定义:一种异步通信组件,用于在分布式系统中解耦生产者和消费者,实现可靠、可扩展、高吞吐的消息传递。

核心模型
- 生产者(Producer):发送消息到队列。
- 队列(Queue):存储消息的缓冲区(如 RabbitMQ、Kafka、Redis Streams)。
- 消费者(Consumer):从队列拉取或由队列推送消息进行处理。

常见模式
- 点对点(Queue):一条消息只被一个消费者处理(任务队列)。
- 发布/订阅(Topic/Exchange):一条消息被多个消费者订阅(广播)。

典型场景
- 异步处理:用户注册后发送欢迎邮件 → 不阻塞响应,放入队列让后台消费。
- 削峰填谷:秒杀系统将请求先写入队列,后端逐步处理,防止数据库被打死。
- 系统解耦:订单完成后,支付服务、库存服务、物流服务通过订阅“订单完成”消息来分别处理,互不依赖。
- 日志收集:应用将日志发往 Kafka,多个消费者分别做存储、分析、告警。

优点
- 提高系统可伸缩性和弹性(消费者可以动态增减)。
- 缓冲突发流量,防止系统过载。
- 提供可靠重试和死信队列,减少失败丢失。

缺点
- 增加系统复杂性和运维负担(需要管理消息中间件)。
- 消息顺序性、重复消费、消息积压等问题需要额外设计。


5. 缓存

定义:将数据副本存储在访问速度更快的存储介质中(如内存),以加速后续访问,减少对后端慢速存储(如数据库)的压力。

常见层级
- 浏览器缓存(HTTP Cache-Control、Expires)
- CDN 缓存(静态资源)
- 反向代理缓存(如 Nginx、Varnish)
- 进程内缓存(如 Python functools.lru_cache、Guava Cache)
- 分布式缓存(如 Redis、Memcached)

缓存模式
- 旁路缓存(Cache Aside):应用先读缓存,如果未命中则读数据库并回填缓存。
- 只读缓存(Read-Through):缓存组件自身负责回源加载。
- 写穿透(Write-Through):写操作同时更新缓存和数据库。
- 写回(Write-Behind):先写缓存,异步批量写数据库(高风险,可能丢数据)。

常见问题与解决
- 缓存穿透:查询不存在的数据,大量请求直达数据库 → 使用布隆过滤器或缓存空结果。
- 缓存雪崩:大量缓存同时失效,请求涌向数据库 → 设置随机过期时间或使用热点数据永不过期+后台异步更新。
- 缓存击穿:某个热点数据失效,高并发请求同时穿透 → 使用互斥锁(如 Redis SETNX)或“永远不过期”。

为什么重要
- 数据库 IO 通常是系统的瓶颈,缓存能将读性能提升几个数量级(毫秒 → 微秒级)。
- 尤其适用于读多写少、计算开销大的场景。

与消息队列的区别:缓存用于加速读/写,消息队列用于异步通信和解耦。


架构演进路径图

单体架构(前后端混合)
      │
      ▼
前后端分离(后端仍是单体)
      │
      ├── 继续单体(模块化单体)── 适用于中小型团队
      │
      └── 拆分为微服务 ── 适用于大规模、多团队
                │
                ├── 需要消息队列进行异步解耦
                ├── 需要分布式缓存提升性能
                └── 需要 API 网关、服务发现等设施

选择建议

场景 推荐架构
个人项目、原型验证 单体(前端不分离或简单模板)
小型产品(3-5 人团队) 前后端分离 + 单体后端(模块化)
中等规模(10 人以上,多端) 前后端分离 + 单体后端(或按领域模块划分)
大型系统(多团队,高并发) 微服务 + 消息队列 + 缓存 + 服务网格
极高并发、读多写少 缓存优先(甚至全部缓存) + 异步落盘

不需要过度设计:如果团队没有运维分布式系统的能力,微服务会带来灾难。很多成功产品长期保持模块化单体,只在必要时拆分。


小结

概念 核心定位 典型技术
单体架构 所有功能打包成一个应用 Django、Spring Boot、Rails
前后端分离 UI 与 API 解耦 React/Vue + DRF/Flask/Spring MVC
微服务 按业务垂直拆分后端 Spring Cloud、Kubernetes、gRPC
消息队列 异步解耦、削峰 RabbitMQ、Kafka、Redis Streams
缓存 加速读、减压后端 Redis、Memcached、CDN