DDIA 1-2 定义非功能性需求
性能 · 可靠性 · 可伸缩性 · 可维护性
(用最简单的话,把概念关系讲清楚)
1. 这章到底在说什么?
软件系统除了“功能要能用”之外,还必须 快、稳、能扩、好维护。
这一章介绍的就是这四个关键的“非功能性需求”:
| 非功能性需求 | 目的 | 在本章里的关键点 |
|---|---|---|
| 性能(Performance) | 系统要快 | 响应时间、吞吐量、百分位数、延迟 |
| 可靠性(Reliability) | 系统不能出错或挂掉 | 故障 vs 失效、容错、硬件/软件/人为故障 |
| 可伸缩性(Scalability) | 负载变大还能扛 | 负载描述、横向/纵向扩展、共享 nothing 架构 |
| 可维护性(Maintainability) | 系统能改、能管 | 可操作性、简单性、可演化性 |
四者之间的关系:
- 性能是用户体验最直观的。
- 可靠性保证系统不“突然死掉”。
- 可伸缩性保证“变大之后还能保持性能和可靠性”。
- 可维护性保证系统能在多年后仍能不断被改进。
它们相互影响、互相支撑:
性能和可靠性是短期用户体验,可伸缩性和可维护性是长期系统质量。
2. 用社交网络首页时间线讲清楚这四件事
书中用“类似 Twitter 的时间线系统”作为贯穿案例。
2.1 基础模型:关注关系 + 帖子
- 用户可以发帖、关注他人。
- 读操作最重要:读取“首页时间线”。
2.2 性能瓶颈:查询太贵
直接查询关注的 200 人的最新帖子 → 每秒数百万重查询 → 不可能。
2.3 解决方案:物化时间线(Materialized Timeline)
把每次发的帖 提前写入粉丝的时间线(扇出 fan-out),然后 read 很快。
3. 性能(Performance)
性能主要看两个指标:
3.1 ① 吞吐量(Throughput)
系统每秒能处理多少请求
(例如每秒发 5,700 条帖子、100 万次写入时间线)
3.2 ② 响应时间(Response Time)
用户发起一个请求,到响应返回的时间。
响应时间不是固定的,是 分布,要用 百分位数(p50 / p95 / p99) 描述:
- p50(中位数):典型用户体验
- p95 / p99:尾部延迟(少量慢请求)
- p999:极端慢请求
百分位数比平均值更真实,因为平均值容易被极慢请求拖歪。
3.3 延迟组成(为什么会慢?)
- 服务处理时间
- 网络延迟
- 排队延迟(最重要,尤其在高负载)
3.4 性能与可伸缩性的联系
什么时候需要扩容?
→ 当吞吐量逼近系统极限、排队变长、p99 变慢。
4. 可靠性(Reliability)
可靠性关注的是:
系统“出问题”时是否还能正常对外提供服务。
关键概念:
4.1 故障(Fault) vs 失效(Failure)
- 故障:部分组件坏了(某台机器挂了)
- 失效:整个系统无法提供服务(整个网站挂了)
可靠系统必须能容忍故障不变成失效。
4.2 容错(Fault Tolerance)
通过冗余、数据副本、心跳检测、failover 等方式确保部分节点坏了系统仍能工作。
4.3 三类故障来源
- 硬件故障(磁盘坏、机器挂、电源出问题)
- 软件故障(bug、内存泄漏、闰秒导致挂死)
- 人为故障(配置错误、误操作)
特别是软件故障往往是“高相关性”的,会导致大面积宕机。
4.4 提升可靠性的手段
- 冗余、数据备份
- 故障注入(Chaos Engineering)
- 自动化运维
- 无责备事后分析(blameless postmortem)
5. 可伸缩性(Scalability)
可伸缩性关注的是:
当负载变大时,系统能否保持性能不变。
5.1 负载(Load)要怎么描述?
- 每秒请求数
- 并发在线用户数
- 数据大小增长率
- 读/写比例
- 极端用户(例如粉丝 1 亿的名人)
描述负载之后,才知道系统瓶颈在哪里。
5.2 两种扩展方式
① 纵向伸缩(Scale Up)
买更大的机器
优点:简单
缺点:贵、有天花板
② 横向伸缩(Scale Out)
加更多的机器,通过分布式系统协作
优点:可以无限扩
缺点:复杂(需要分片、容错、分布式协议等)
5.3 共享架构类型
- 共享内存(shared memory):同一台机器多线程共享 RAM
- 共享磁盘(shared disk):多机器使用同一存储
- 无共享架构(shared nothing):每台机器独立运行(主流)
无共享架构是现代互联网系统的核心。
6. 可维护性(Maintainability)
可维护性关注的是:
系统能否长期演进、好维护、不变成大泥球。
可维护性分为三个子目标:
6.1 可操作性(Operability)
让运维更容易,例如:
- 可观察性(logs / metrics / tracing)
- 自动化部署
- 能安全地滚动升级
- 错误处理可预测
6.2 简单性(Simplicity)
减少偶然复杂性,让系统更容易理解。
这里强调了本质复杂性 vs 偶然复杂性:
- 本质复杂性:问题本身就难(例如大规模社交图结构)
- 偶然复杂性:工具、框架、实现方式带来的额外麻烦(可避免)
减少偶然复杂性 → 提高可维护性。
6.3 可演化性(Evolvability)
系统随着需求变化能轻松修改,比如:
- 数据库迁移可回滚
- 模块松耦合
- 架构能支持未预料的用例
本质是:
系统越易改 → 越能在多年后保持生命力。
7. 四大非功能性需求之间的关系总结
下面是最关键的关系图(大白话版):
性能(快)
↑ ↘
| 可伸缩性(负载变大仍保持快)
|
可靠性(不挂) ↗
|
可维护性(能改、能运维)
换成一句话:
性能决定体验,可靠性保证不会挂,可伸缩性保证变大也不挂,可维护性保证未来还能变好。
它们互相补充,是现代数据密集型系统的共同目标。
8. 本章的核心 takeaway(精华)
- 性能:用响应时间百分位数衡量真实体验
- 可靠性:关键是容错,让故障不变成系统失效
- 可伸缩性:描述负载、发现瓶颈、用横向扩展解决
- 可维护性:减少复杂度、提升可操作性、保证系统可演化
理解这些概念,是后续章节(复制、分片、事务、一致性、流处理等)的基础。