可扩展性、高可用与性能设计
一、水平与垂直扩展
垂直扩展(Scale up):给单机加 CPU、内存、磁盘,提升单机能力。实现简单、无需改架构,但有物理与成本上限,且单点故障影响大。
水平扩展(Scale out):通过增加机器数量来提升整体能力,负载均衡把请求分到多台实例。理论上可线性加机器,但要解决无状态(或状态外置)、数据与会话分布、一致性与路由等问题。互联网系统通常以水平扩展为主,垂直扩展作为单机优化补充。
二、无状态与有状态
无状态:服务不把「当前请求以外的」会话或上下文存在本机内存,请求之间互不依赖本机状态。这样任意请求可被任意实例处理,便于水平扩展与故障转移。会话若需要则放到外部(Redis、Cookie 或 JWT 等)。
有状态:服务在本机保存会话或本地数据,请求与某台实例绑定(sticky)。便于实现某些本地缓存或低延迟状态访问,但扩缩容与故障时要考虑状态迁移或会话丢失。若必须保留状态,可把状态集中到共享存储或按 key 路由到固定节点,并做好复制与恢复。
三、高可用:冗余、故障隔离、熔断与降级
冗余:关键组件无单点——多实例、多可用区、主从/多活。任一节点或机房故障时,流量与数据可由其他节点接管。配合健康检查与负载均衡,自动摘除故障节点。
故障隔离:限制故障传播范围。例如线程池/进程隔离、舱壁模式(bulkhead)、或按服务/用户隔离,避免一个慢依赖拖垮整个系统。超时与限流也是隔离手段。
熔断(Circuit breaker):当依赖调用失败率或延迟超过阈值时,熔断器「打开」,短时间内不再请求该依赖,直接返回失败或降级结果,避免雪崩。过一段时间再尝试「半开」探测,成功则关闭熔断恢复调用。
降级(Degradation):在系统压力大或依赖不可用时,关闭或简化非核心功能,保证核心路径可用。例如关闭推荐、只读不写、返回缓存或默认值。降级策略要事先设计好开关与层级。
高可用要点
- 冗余:多实例、多可用区、去单点,配合健康检查与 LB
- 故障隔离:线程/进程/服务隔离、超时与限流,避免雪崩
- 熔断:失败率/延迟超阈值则停调依赖,半开探测后恢复
- 降级:压力或依赖不可用时关非核心、保核心路径
四、性能设计:缓存、异步、批处理
缓存:把热点数据放在更近或更快的存储(本地内存、Redis、CDN),减少重复计算与下游请求。要考虑失效策略(TTL、主动失效)、一致性(写时失效或延迟一致)、穿透/击穿/雪崩(空值缓存、锁、过期分散)等问题。
异步:非实时必要的操作放到队列或异步任务中执行,请求先快速返回。例如写日志、发通知、报表生成。可削峰、提高吞吐,但语义变为最终一致,需幂等与补偿。
批处理:把多次小请求合并成一批(如批量读 DB、批量写日志),减少往返与锁竞争。适合高吞吐、可接受少量延迟的场景;注意批次大小与超时。
五、非功能需求的架构化实现
可扩展性、高可用、性能、安全等非功能需求不能只靠「写代码时注意」,而要通过架构与机制保障。例如:用多实例与 LB 实现扩展与冗余、用熔断与降级实现故障隔离、用缓存与异步实现性能目标、用认证鉴权与加密实现安全。在需求与设计阶段就要明确 NFR 指标(如可用性 99.9%、P99 延迟 < 200ms),并在架构评审与运维中持续验证。把「非功能」当成一等公民,才能让系统长期稳、快、可演进。
非功能需求落地要点
- 在需求与设计阶段明确 NFR 指标(可用性、延迟、吞吐等)
- 用架构与机制保障:冗余、隔离、熔断降级、缓存异步等
- 在架构评审与监控中持续验证,非功能与功能同等重要
一句话: 可扩展靠垂直堆配置或水平加机器(无状态更易水平扩);高可用靠冗余、故障隔离、熔断与降级;性能靠缓存、异步、批处理;非功能需求要在架构与机制中显式落地并持续验证。
六、小结
扩展:垂直加配置、水平加节点,无状态便于水平扩。高可用:冗余去单点、隔离限故障、熔断防雪崩、降级保核心。性能:缓存减重复、异步削峰、批处理减往返。非功能:指标明确、架构保障、持续验证。下一章讲遗留系统与技术债务,从技术债务识别到 strangler fig、防腐层与何时重写。