跳转到主要内容

19.1 先写服务需求

部署的第一行不应是:

pg_version: 18

而应是:

这个服务为何存在?
什么数据不能丢?
什么操作不能错?
谁承担结果?
失败多久开始造成不可接受损失?

如果这些问题没有答案,CPU、节点数、同步复制和备份频率都只能靠猜。

19.1.1 业务重要性、数据分类与所有者

先定义业务能力

pg36_shop 提供的不是“一个 database”,而是:

商品浏览与检索
客户身份与地址
订单创建和状态转换
库存与支付事实
配送时空事件
分析与外部投影源

不同能力的故障损失不同:

能力 失败影响 可接受降级
创建订单 直接收入/履约风险 拒绝比重复创建安全
查询支付状态 财务与客服风险 不可用旧缓存猜测
商品描述 转化下降 可短时有标签陈旧
搜索排序 发现能力下降 可回退简单检索
分析报表 决策延迟 可显示 last watermark
图片读取 体验下降 placeholder/重试

一个统一 database 可以承载它们,但 service objective 不能只写一个“重要”。

业务重要性需要损失模型

常用分级:

tier 0 / critical
  停止即产生重大安全、财务或合规损失

tier 1 / important
  核心业务中断,短时可人工/降级

tier 2 / standard
  影响明显,但可在较长窗口恢复

tier 3 / development
  无生产承诺,可重建

分级必须连接动作:

critical standard development
owner/on-call 24×7 明确 支持窗口明确 工作时间
HA 多故障域并演练 按目标设计 可无
backup 跨域、频繁演练 标准恢复 可选且声明
change 强审批/回退 标准流程 自助边界
capacity 高 headroom 正常 headroom best effort
incident 快速升级 标准升级 issue

若分级只改变标签颜色,就没有价值。

数据分类决定安全与恢复边界

分类至少包含:

public
internal
confidential
restricted / regulated
credentials and cryptographic material

对每类记录:

  • 数据 owner;
  • 合法用途;
  • 可访问角色;
  • 是否可复制到 dev/test;
  • 加密与审计要求;
  • 地域限制;
  • retention;
  • 删除时限;
  • backup 中如何处理;
  • incident 通知义务。

本章正式 sandbox 只允许:

synthetic teaching data
production_data_permitted=false
production_traffic_permitted=false

这是硬边界。VM 看起来像生产拓扑,也不能把生产数据“临时导入测试”。

数据 owner 与平台 owner 不同

建议至少区分:

角色 责任
business/data owner 数据用途、正确性、分类、保留、损失
service owner SLO、错误预算、依赖、发布、事件
database platform PostgreSQL/Pigsty、HA、备份、接入、容量
security/privacy 威胁、控制、审计、合规
application team schema/SQL、连接、重试、兼容、流量
incident commander 事件期协调和决策

一个人可以兼任,责任不能消失。

owner 要能作决定

在事故中,DBA 可以说:

“当前恢复到 10:31 会丢 47 秒提交,
 恢复到最新可能保留错误写入。”

但通常不能独自决定哪种业务损失更小。需要提前指定有权选择:

availability versus consistency
restore point
degraded operation
data deletion
customer communication
error-budget spend

“负责人:数据库团队”太宽泛。最终要映射到值班角色、升级路径和替代人。

数据清单要包含派生副本

第 18 章已经定义:

PostgreSQL authoritative business state
cache projection
event delivery/replay log
object bytes
search projection
analytical projection
backup/WAL copies

部署规划不能只列 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,但不要泄密

配置可保存:

service_class: pg-ha-standard
data_class: confidential
owner: shop-order-team

不应把:

customer data samples
passwords
private keys
recovery secrets
token values

写入基线报告。

本章的 inventory projection 只输出安全 allowlist,记录:

source mode
secret-bearing source fingerprint withheld
safe projection sha256
secret fields redacted count
secret values exported = 0

它证明审计过程知道 secret 存在,同时不把值复制到 evidence。

未知 owner 是阻断项

没有 owner 的 service 不应进入生产。原因很现实:

  • 谁批准 maintenance?
  • 谁判断数据正确?
  • 谁接 incident 电话?
  • 谁接受 RPO?
  • 谁决定退役?
  • 谁支付容量?

可以在 sandbox 用 placeholder,但 production gate 必须把 placeholder 映射到 真实责任人/组和升级路径。

pg36_shop 的当前需求身份

本章 requirements.json 写的是:

service=pg36_shop
data=synthetic teaching only
business owner=placeholder
platform owner=placeholder
target=disposable local Linux sandbox
production approval=false

所以它可以验收部署流程,不能通过真实 pg-ha-standard 的 owner/data gate。

19.1.2 负载形态、增长、峰谷和批处理窗口

“OLTP”不是容量需求

同为 OLTP,可能分别是:

10k tiny point reads/s
500 write transactions/s with 20 indexes
50 large JSON updates/s
100 concurrent long business transactions
bursty checkout traffic
multi-tenant mixed workload

需要一份 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 的四类负载形状:

transactional
  selective, short, latency-sensitive, correctness first

search
  rank/filter, index-heavy, quality + latency

spatiotemporal
  GiST, range, event ingest, retention

analytics
  large scan/aggregate, temp/parallel, freshness-tolerant

如果只用总 QPS,分析扫描和订单写入会互相隐藏。

每类要记录:

endpoint/role
timeout
resource priority
expected concurrency
allowed replica/freshness
degradation
owner

峰值不是日均乘一个系数

峰值来源:

营销活动
整点任务
工资/账单周期
客户端 retry
故障流量转移
缓存失效
批处理重跑
schema migration
backup/checkpoint overlap

真实 peak envelope 至少有:

amplitude
duration
ramp rate
frequency
correlated workloads
recovery tail

一分钟 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 需要重建。

增长要分逻辑与物理

逻辑增长:

customers
products
orders/day
items/order
events/day
tenants
retention days

物理增长:

heap
TOAST
indexes
dead tuples/bloat
WAL
temp peak
replicas
backup full/diff/incr
archive retention
monitoring/logs
external projections

一个粗略存储模型:

[ capacity = (heap + toast + indexes + free\ space) \times replica\ factor

  • backup/archive
  • maintenance/upgrade\ headroom ]

不能直接拿业务 CSV 大小乘副本数。

使用增长曲线,不只用线性外推

记录:

daily/weekly sample
seasonality
new feature step changes
largest tenant
retention changes
index additions
compression/archival
confidence interval

容量到达时间:

[ T_{exhaust}

\frac{usable\ capacity - current\ usage - required\ headroom} {growth\ rate} ]

增长率有区间时给出 earliest/expected,而不是一个虚假精确日期。

批处理窗口是一项共享资源预约

批任务包括:

ETL/export
materialized refresh
search/vector rebuild
backup
VACUUM/ANALYZE
index build
partition lifecycle
financial close
data quality reconciliation

每项保存:

字段 意义
earliest start / deadline 可运行窗口
duration distribution 不只平均
CPU/I/O/WAL/temp 资源
locks/snapshot 并发影响
retry 是否会叠加
freshness 延迟后果
owner 谁停止/恢复
conflict priority 与交易冲突时谁让路

“晚上跑”不是窗口。跨时区业务可能没有真正夜间。

维护和业务峰值要画在同一时间轴

建议按 UTC 画一周:

online traffic
batch
backup
checkpoint/WAL archive
autovacuum debt
reporting
deploy
on-call coverage

你可能发现:

业务低谷
  = backup full
  = ETL full scan
  = index maintenance
  = replica lag peak

所谓低谷实际上是数据库最忙时段。

负载可回放性

为了比较环境,保存:

schema/version
data generator or anonymized snapshot identity
query fingerprints
parameter/selectivity distribution
arrival model
connection/pool model
background jobs
warm/cold cache protocol
duration
random seed
success and correctness golden

只保存一条 pgbench -c 100 命令不足以代表业务。

sandbox 的资源结论边界

本章为 Vagrant sandbox 建议每台至少:

>= 2 logical CPUs
>= 2 GiB memory
>= 8 GiB root free
swap = 0

这些只是教学环境的建议下限,不是 pg36_shop 的生产容量规格。正式实验中, 三台 pg-test VM 只有 1 个 vCPU、约 1.9 GiB 内存;部署虽然完成,但必须以 EX19-LAB-RESOURCE-FLOOR 记录偏差,不能把成功运行反推为资源充足。

四台 VM 共享一台 laptop 的:

CPU
memory controller
physical storage
power
hypervisor
host network

因此任何 benchmark 都不能外推生产。

需求表中的 unknown

本章刻意不为以下项目造数字:

production QPS
production data growth
production storage latency
production connection budget
production batch window

它们进入第 24、26、27 章。部署基线的职责是让 unknown 可见,并阻止默认值被 误报为需求。

19.1.3 可用性、RPO、RTO 与维护窗口

四个概念先分开

availability
  服务在测量窗口内按定义成功的比例

RPO
  可接受的数据恢复点损失

RTO
  从场景发生到服务恢复到规定状态的时间

maintenance window
  允许计划变更及其用户影响的时间边界

它们相关,但不能互相替代。

三节点自动 failover 可能有较短可用性中断,却无法恢复昨天误删的数据;一天 一次 full backup 可能可恢复,却不提供当前 primary HA。

先定义成功请求

可用性分母和成功必须明确:

哪些 endpoint
哪些 operation
哪些用户/区域
什么状态码/SQLSTATE
正确性是否计入
延迟阈值
陈旧度阈值
测量位置
计划维护是否排除

如果数据库返回 200/row 但金额错误,不应算可用。

“几个九”换算为时间只是直觉

以 30 天窗口为例:

目标 粗略不可用预算
99% 7h 12m
99.9% 43m 12s
99.95% 21m 36s
99.99% 4m 19s

真正 SLO 仍由事件型 SLI 计算,不能只用服务器 uptime。

RPO 必须绑定故障场景

示例:

single replica loss       RPO 0
primary failover          async lag within measured policy
sync-confirmed commit     RPO 0 only in modeled sync failure domain
operator DROP             PITR target before error
storage corruption        last verified clean recovery point
region loss               cross-domain repository/standby position

“RPO=0”若没有场景和确认语义,就是不完整承诺。

应用还要知道:

client got success -> commit durability promise
client got timeout -> outcome unknown, must query by idempotency key

RTO 从开始点到结束点

RTO 的起点可能是:

physical failure
monitor detects
alert reaches human
incident declared
recovery decision

终点可能是:

database accepts connections
write service healthy
business golden passes
backlog caught up
all clients restored

如果不定义,两个团队报告的 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 是预算,不是免责

维护窗口应记录:

frequency
duration
notice
allowed impact
rollback deadline
business blackout dates
owner approval
post-check

即使计划维护被 SLO 排除,用户损失仍存在。高成熟度平台会:

  • 滚动维护;
  • 验证连接恢复;
  • 限制每次 blast radius;
  • 保留 rollback;
  • 记录实际中断;
  • 复审窗口是否足够。

升级窗口必须包含回退判断

不只计算安装时间:

preflight
backup/recovery point
traffic drain
package/schema change
restart/failover
application golden
observation
rollback or forward decision

有些 PostgreSQL major upgrade 在数据目录切换后没有简单 rollback;最后可逆 点必须写清。第 30 章专门演练。

服务目标从损失与成本共同推导

目标越强,通常需要:

more independent replicas
synchronous distance/latency trade-off
more recovery copies
more frequent drills
more on-call coverage
more capacity headroom
more change discipline

不能只问“技术上能否做到”,还要问业务是否愿意持续支付,以及组织能否操作。

本章不通过第 20/21 章

第 19 章只验证环境前提:

hosts distinct
versions/initialization uniform
declared and live topology agree
endpoints exist
roles/services active
exceptions explicit

它不注入故障,不执行 failover,不做 restore。因此:

ch20-ha = pending
ch21-backup-restore = pending

sandbox 的准确结论

本章四节点能证明:

one pg-meta member
three pg-test members
one live leader
two live replicas
one offline-query declaration
Pigsty inventory/host/Patroni/SQL facts agree

不能证明:

four production failure domains
production RPO/RTO
production storage durability
production capacity
production secret lifecycle

因为所有 VM 共享物理 laptop,etcd 与 backup target 也各只有一个控制节点。

把例外当结构化结果

requirements.json 固定六项 sandbox exception:

EX19-SHARED-HYPERVISOR
EX19-SINGLE-ETCD
EX19-SINGLE-BACKUP-TARGET
EX19-VIRTUAL-STORAGE
EX19-INVENTORY-SECRETS
EX19-LAB-RESOURCE-FLOOR

通过结果必须写:

sandbox_l2=accepted-with-exceptions
production_ch19_gate=pending

“验收通过”后面没有范围,是一种危险省略。


返回本章目录 · 下一节:计算、内存、存储与网络 · 查看全书目录 · 查看索引中心