19.1 先写服务需求
部署的第一行不应是:
而应是:
如果这些问题没有答案,CPU、节点数、同步复制和备份频率都只能靠猜。
19.1.1 业务重要性、数据分类与所有者
先定义业务能力
pg36_shop 提供的不是“一个 database”,而是:
不同能力的故障损失不同:
| 能力 | 失败影响 | 可接受降级 |
|---|---|---|
| 创建订单 | 直接收入/履约风险 | 拒绝比重复创建安全 |
| 查询支付状态 | 财务与客服风险 | 不可用旧缓存猜测 |
| 商品描述 | 转化下降 | 可短时有标签陈旧 |
| 搜索排序 | 发现能力下降 | 可回退简单检索 |
| 分析报表 | 决策延迟 | 可显示 last watermark |
| 图片读取 | 体验下降 | placeholder/重试 |
一个统一 database 可以承载它们,但 service objective 不能只写一个“重要”。
业务重要性需要损失模型
常用分级:
分级必须连接动作:
| 项 | critical | standard | development |
|---|---|---|---|
| owner/on-call | 24×7 明确 | 支持窗口明确 | 工作时间 |
| HA | 多故障域并演练 | 按目标设计 | 可无 |
| backup | 跨域、频繁演练 | 标准恢复 | 可选且声明 |
| change | 强审批/回退 | 标准流程 | 自助边界 |
| capacity | 高 headroom | 正常 headroom | best effort |
| incident | 快速升级 | 标准升级 | issue |
若分级只改变标签颜色,就没有价值。
数据分类决定安全与恢复边界
分类至少包含:
对每类记录:
- 数据 owner;
- 合法用途;
- 可访问角色;
- 是否可复制到 dev/test;
- 加密与审计要求;
- 地域限制;
- retention;
- 删除时限;
- backup 中如何处理;
- incident 通知义务。
本章正式 sandbox 只允许:
这是硬边界。VM 看起来像生产拓扑,也不能把生产数据“临时导入测试”。
数据 owner 与平台 owner 不同
建议至少区分:
| 角色 | 责任 |
|---|---|
| business/data owner | 数据用途、正确性、分类、保留、损失 |
| service owner | SLO、错误预算、依赖、发布、事件 |
| database platform | PostgreSQL/Pigsty、HA、备份、接入、容量 |
| security/privacy | 威胁、控制、审计、合规 |
| application team | schema/SQL、连接、重试、兼容、流量 |
| incident commander | 事件期协调和决策 |
一个人可以兼任,责任不能消失。
owner 要能作决定
在事故中,DBA 可以说:
但通常不能独自决定哪种业务损失更小。需要提前指定有权选择:
“负责人:数据库团队”太宽泛。最终要映射到值班角色、升级路径和替代人。
数据清单要包含派生副本
第 18 章已经定义:
部署规划不能只列 primary 数据目录。数据流 inventory 应记录:
| 副本 | authority | freshness | retention | deletion | rebuild |
|---|---|---|---|---|---|
| replica | PostgreSQL | replay lag | current | follows WAL | base backup |
| backup | historical recovery | backup/WAL | policy | retention expiry | restore |
| cache | derived | TTL/version | eviction | tombstone/TTL | source refill |
| event bus | delivery log | publish lag | broker policy | workflow | replay/snapshot |
| lake/search | projection | watermark | generation | tombstone | rebuild |
这些副本会影响存储、网络、密钥和故障域规划。
分类要进入 inventory 与 evidence,但不要泄密
配置可保存:
不应把:
写入基线报告。
本章的 inventory projection 只输出安全 allowlist,记录:
它证明审计过程知道 secret 存在,同时不把值复制到 evidence。
未知 owner 是阻断项
没有 owner 的 service 不应进入生产。原因很现实:
- 谁批准 maintenance?
- 谁判断数据正确?
- 谁接 incident 电话?
- 谁接受 RPO?
- 谁决定退役?
- 谁支付容量?
可以在 sandbox 用 placeholder,但 production gate 必须把 placeholder 映射到 真实责任人/组和升级路径。
pg36_shop 的当前需求身份
本章
requirements.json
写的是:
所以它可以验收部署流程,不能通过真实 pg-ha-standard 的 owner/data gate。
19.1.2 负载形态、增长、峰谷和批处理窗口
“OLTP”不是容量需求
同为 OLTP,可能分别是:
需要一份 workload inventory:
| 维度 | 例 |
|---|---|
| transaction classes | browse/order/pay/admin |
| read/write ratio | 分类别 |
| statements/transaction | 分布 |
| rows touched | P50/P95/P99 |
| connection behavior | pool、active、idle |
| latency | P50/P95/P99/timeout |
| concurrency | arrival、active、parallel |
| WAL | bytes/s 与 burst |
| temp | bytes/query 与 aggregate |
| locks | wait、deadlock、long xact |
| maintenance | vacuum/index/backup |
第 26 章才正式做容量曲线,本章先确保环境规划有输入。
交易、搜索、空间与分析分开建模
pg36_shop 的四类负载形状:
如果只用总 QPS,分析扫描和订单写入会互相隐藏。
每类要记录:
峰值不是日均乘一个系数
峰值来源:
真实 peak envelope 至少有:
一分钟 10 倍峰值与持续 4 小时 3 倍峰值需要不同资源和降级。
流量转移后的单节点峰值
三节点 topology 正常时,读流量可分散;一台 replica 故障后:
[ load_{remaining}
\frac{total\ eligible\ load}{remaining\ eligible\ capacity} ]
若两个 replica 平时各 50%,失去一个后另一个可能接近 100%,也可能 fallback 到 primary。容量必须按 failure state 规划,不只按 happy path。
同理,failover 后:
- 新 primary 承接全部写;
- cache 冷;
- client 重连;
- replica 重新追赶;
- backup/maintenance 可能仍在;
- 旧 primary 需要重建。
增长要分逻辑与物理
逻辑增长:
物理增长:
一个粗略存储模型:
[ capacity = (heap + toast + indexes + free\ space) \times replica\ factor
- backup/archive
- maintenance/upgrade\ headroom ]
不能直接拿业务 CSV 大小乘副本数。
使用增长曲线,不只用线性外推
记录:
容量到达时间:
[ T_{exhaust}
\frac{usable\ capacity - current\ usage - required\ headroom} {growth\ rate} ]
增长率有区间时给出 earliest/expected,而不是一个虚假精确日期。
批处理窗口是一项共享资源预约
批任务包括:
每项保存:
| 字段 | 意义 |
|---|---|
| earliest start / deadline | 可运行窗口 |
| duration distribution | 不只平均 |
| CPU/I/O/WAL/temp | 资源 |
| locks/snapshot | 并发影响 |
| retry | 是否会叠加 |
| freshness | 延迟后果 |
| owner | 谁停止/恢复 |
| conflict priority | 与交易冲突时谁让路 |
“晚上跑”不是窗口。跨时区业务可能没有真正夜间。
维护和业务峰值要画在同一时间轴
建议按 UTC 画一周:
你可能发现:
所谓低谷实际上是数据库最忙时段。
负载可回放性
为了比较环境,保存:
只保存一条 pgbench -c 100 命令不足以代表业务。
sandbox 的资源结论边界
本章为 Vagrant sandbox 建议每台至少:
这些只是教学环境的建议下限,不是 pg36_shop 的生产容量规格。正式实验中,
三台 pg-test VM 只有 1 个 vCPU、约 1.9 GiB 内存;部署虽然完成,但必须以
EX19-LAB-RESOURCE-FLOOR 记录偏差,不能把成功运行反推为资源充足。
四台 VM 共享一台 laptop 的:
因此任何 benchmark 都不能外推生产。
需求表中的 unknown
本章刻意不为以下项目造数字:
它们进入第 24、26、27 章。部署基线的职责是让 unknown 可见,并阻止默认值被 误报为需求。
19.1.3 可用性、RPO、RTO 与维护窗口
四个概念先分开
它们相关,但不能互相替代。
三节点自动 failover 可能有较短可用性中断,却无法恢复昨天误删的数据;一天 一次 full backup 可能可恢复,却不提供当前 primary HA。
先定义成功请求
可用性分母和成功必须明确:
如果数据库返回 200/row 但金额错误,不应算可用。
“几个九”换算为时间只是直觉
以 30 天窗口为例:
| 目标 | 粗略不可用预算 |
|---|---|
| 99% | 7h 12m |
| 99.9% | 43m 12s |
| 99.95% | 21m 36s |
| 99.99% | 4m 19s |
真正 SLO 仍由事件型 SLI 计算,不能只用服务器 uptime。
RPO 必须绑定故障场景
示例:
“RPO=0”若没有场景和确认语义,就是不完整承诺。
应用还要知道:
RTO 从开始点到结束点
RTO 的起点可能是:
终点可能是:
如果不定义,两个团队报告的 RTO 可以相差整个检测与验证阶段。
建议分解:
[ RTO = detection
- decision
- execution
- validation
- traffic\ restoration ]
每段都能优化,也都可能失败。
HA RTO 与 restore RTO 不同
| 场景 | 路径 |
|---|---|
| primary host loss | detect → elect → promote → route → client retry |
| database deleted | stop damage → choose target → restore → replay → validate |
| corrupt pages | preserve evidence → classify → restore/rebuild → validate |
| region loss | activate remote infra → restore/promote → dependencies → DNS |
不要用 Patroni failover 的秒数回答整库恢复需要多久。
maintenance 是预算,不是免责
维护窗口应记录:
即使计划维护被 SLO 排除,用户损失仍存在。高成熟度平台会:
- 滚动维护;
- 验证连接恢复;
- 限制每次 blast radius;
- 保留 rollback;
- 记录实际中断;
- 复审窗口是否足够。
升级窗口必须包含回退判断
不只计算安装时间:
有些 PostgreSQL major upgrade 在数据目录切换后没有简单 rollback;最后可逆 点必须写清。第 30 章专门演练。
服务目标从损失与成本共同推导
目标越强,通常需要:
不能只问“技术上能否做到”,还要问业务是否愿意持续支付,以及组织能否操作。
本章不通过第 20/21 章
第 19 章只验证环境前提:
它不注入故障,不执行 failover,不做 restore。因此:
sandbox 的准确结论
本章四节点能证明:
不能证明:
因为所有 VM 共享物理 laptop,etcd 与 backup target 也各只有一个控制节点。
把例外当结构化结果
requirements.json
固定六项 sandbox exception:
通过结果必须写:
“验收通过”后面没有范围,是一种危险省略。
返回本章目录 · 下一节:计算、内存、存储与网络 · 查看全书目录 · 查看索引中心