用途
系统设计模式技能用于设计可扩展、可靠且高性能的系统,提供经过验证的模式参考。适用场景包括:设计新系统或新功能、评估架构权衡、规划规模扩展、提升系统可靠性、做出基础设施决策。
核心原则
CAP 定理
- 一致性(Consistency):所有节点看到相同数据,代价是更高延迟。
- 可用性(Availability):系统响应每个请求,可能返回过期数据。
- 分区容错性(Partition Tolerance):系统在网络故障下仍可工作,必须牺牲 C 或 A。
三者选二:CP 适用于银行、库存等一致性关键场景;AP 适用于社交媒体、缓存等可用性关键场景;CA 仅适用于单节点系统(无网络分区)。
ACID 与 BASE
- ACID(传统关系型数据库):原子性、一致性、隔离性、持久性。
- BASE(分布式):基本可用、软状态、最终一致。
可扩展性模式
水平扩展与垂直扩展
垂直扩展(Scale Up):使用更大的服务器,增加 CPU、内存、存储。优点是实现简单、无需改代码、运维复杂度低;缺点是受硬件限制、单点故障、规模化后成本高。
水平扩展(Scale Out):增加多台服务器。优点是可近乎无限扩展、容错、规模化后成本效益好;缺点是分布式复杂度、数据一致性挑战、运维开销更大。
负载均衡策略
- Round Robin:适用于无状态、同构服务,缺点是无健康感知。
- Weighted Round Robin:适用于服务器容量不同的场景,需手动配置。
- IP Hash:适用于需要会话保持的场景,缺点是分布可能不均。
- Least Connections:适用于长连接,缺点是跟踪有开销。
- Least Response Time:适用于延迟敏感应用。
- Geographic Based:适用于全球用户,缺点是复杂度高。
数据库扩展
读副本
主库处理写入,通过异步复制同步到多个读副本,读查询路由到副本。示例代码展示了在 ABP 中通过只读仓储与写入仓储实现读写分离。
数据库分片
通过分片路由器根据分片键路由查询。分片策略包括:
- 范围分片:简单、范围查询可用,但可能出现热点。
- 哈希分片:分布均匀,但范围查询需要 scatter-gather。
- 目录分片:灵活,但有查找开销和单点故障。
- 地理分片:数据本地化,但跨区域查询慢。
缓存模式
Cache-Aside(懒加载)
先查缓存,未命中则从数据库加载并回填缓存;更新时更新数据库并使缓存失效。
Write-Through
写入数据库的同时同步写入缓存。
缓存策略对比
- Cache-Aside:最终一致,读多场景,如用户资料。
- Write-Through:强一致,读写场景,如金融数据。
- Write-Behind:最终一致,写多场景,如分析、日志。
- Read-Through:最终一致,读多场景,如参考数据。
可靠性模式
断路器
使用 Polly 实现,在连续异常达到阈值后打开断路器,一段时间后进入半开状态测试恢复。
指数退避重试
使用 Polly 的 WaitAndRetryAsync,重试间隔按 2 的幂次增长(如 2、4、8 秒)。
舱壁隔离
通过限制最大并发执行数与最大排队数隔离故障,防止级联失败。
事件驱动架构
消息队列模式
服务 A 发送消息到消息队列(如 RabbitMQ、Kafka、Azure Service Bus),由消费者服务 B、C 等消费。
事件溯源
存储事件而非状态,通过重放事件重建聚合状态。示例展示了 PatientAggregate 通过 Apply 方法应用事件并支持从事件重建。
设计权衡速查
- 存储:SQL 与 NoSQL,考虑数据结构与一致性需求。
- 缓存:Redis 与内存缓存,考虑分布式需求与容量。
- 通信:同步(HTTP)与异步(队列),考虑耦合与延迟容忍度。
- 一致性:强一致与最终一致,考虑业务需求。
- 扩展:垂直与水平,考虑成本、复杂度与限制。
系统设计检查清单
需求(功能与非功能)、规模(预期用户、请求/秒、数据量)、可用性(正常运行时间目标,99.9% 对应每年 8.76 小时停机)、延迟(P50、P95、P99 目标)、数据(存储类型、保留、备份策略)、缓存(缓存内容与失效策略)、安全(认证、加密、合规)、监控(指标、日志、告警)、故障模式(某组件失败时会发生什么)、成本(基础设施与运维开销)。
相关技能
technical-design-patterns(记录设计)、api-design-principles(API 架构)、distributed-events-advanced(事件模式)。