19.5 拓扑、命名与故障域
三台服务器不是高可用拓扑,除非我们知道三台分别会因什么而一起失败。 “主库、从库、VIP”也不是足够精确的词表,尤其在 promotion 之后。
19.5.1 主节点、同步副本、异步副本与仲裁
primary 是当前角色,不是机器身份
PostgreSQL physical replication 中:
promotion 后,原 standby 可以成为 primary。于是:
把 hostname 叫 prod-primary 会在第一次切换后撒谎。
原生证据:
它不单独证明 service routing 正确,也不证明另一台没有同时可写。
physical standby 重放同一条 WAL 历史
同一 cluster 的成员应共享:
官方 Log-Shipping Standby 强调 primary/standby 应尽量相似,physical log shipping 不跨 major。
本章用 system identifier 检查:
异步复制的 commit 不等待副本
streaming replication 默认异步。正常低延迟不等于零 RPO:
数据损失窗口由故障时实际 receive/write/flush/replay 位置决定,而不是 平时 dashboard 上“通常 0 MB”决定。
观察 primary:
本章只确认 replica 在 streaming;第 20 章才测 failure-time 数据包络。
同步复制把一部分 commit latency 换成确认
PostgreSQL synchronous replication 可以让 commit 等待一个或多个 standby 反馈。等待层次包括:
它们不是同义词。remote_apply 还等待 replay 可见,延迟与阻塞代价更高。
配置又分:
同步复制只有在以下条件下才提供期望保护:
- standby 是真实独立故障域;
- storage flush 语义可信;
- synchronous standby 处于 streaming;
- application 没有降级为更弱
synchronous_commit; - 超时/降级策略符合业务选择;
- 失联时是停止写还是降级继续写已经定义。
“有 sync replica”不能省略这些条件。
同步复制也可能让写入不可用
若要求一个同步确认,而没有任何合格 standby:
因此 RPO 与 availability 之间要由 owner 选择:
自动降级如果没有审计,就是悄悄改变服务合同。
“仲裁”不要与数据副本混淆
PostgreSQL core 没有一个保存业务数据的“仲裁节点”概念。Pigsty 的 HA 参考实现里:
etcd member:
- 不保存可 promotion 的 PostgreSQL data;
- 不确认每个业务 transaction 已持久化;
- 不替代 backup;
- 不依据最新 WAL 自动解决所有数据选择;
- 需要自己的 quorum 与 failure domains。
把一个 etcd 节点叫“第三票”,然后声称两台 PostgreSQL 已实现零数据丢失, 是错误模型。
DCS quorum 与数据库成员数分别计算
三节点 PostgreSQL + 单节点 etcd:
三个数字不能互相抵消。单 etcd failure 会影响自动 HA 控制面;同一 laptop failure 会同时失去全部 VM。
本章正式沙箱把这两项登记为:
所以它适合练拓扑与协议,不适合宣称 production availability。
offline replica 是 workload placement
Pigsty 支持专门的 offline instance,也支持在已有 replica 上设置
pg_offline_query: true,把它纳入 offline service。官方
Cluster / Instance
明确说明后一种是资源折中。
本章:
它仍是同一 pg-test physical replica,不是独立 analytical authority。
标记不自动限制 CPU/I/O,也不自动阻止用户绕过 service 直连。第 17、22、
26、30 章分别处理分析语义、服务接入、容量和资源治理。
本章拓扑不是第 20 章结论
本章可以证明:
不能证明:
这些必须用受控 fault drill 取得。
19.5.2 节点、实例、集群、服务的统一词表
同一个“集群”常指四种东西
先建立词表:
| 词 | 本书定义 | 稳定身份/证据 |
|---|---|---|
| host/node | OS 实体:物理机、VM 或明确容器边界 | machine ID、hostname、address |
| PostgreSQL instance | 一个 server process + data directory + port | member name、PGDATA、system ID |
| PostgreSQL database cluster | 一个 initdb 产生的数据目录及其中 databases |
system identifier |
HA cluster / Pigsty pg_cluster |
一组共享 physical history、可相互接管的 members | pg_cluster、Patroni scope |
| database | cluster 内的 SQL database | OID/name/owner/locale |
| service | 面向客户端的稳定访问语义 | name、port、selector、health check |
| pool | 连接复用/状态边界 | PgBouncer endpoint/mode |
| DCS cluster | Patroni 使用的 etcd 共识域 | etcd membership/quorum |
| platform deployment | inventory 管理范围 | exact inventory/release |
PostgreSQL 官方把一个 data directory 称为 database cluster;平台团队又常把 一个 HA group 称 cluster。文档必须说明上下文。
node 不等于 instance
一台 node 可以运行:
一个 PostgreSQL cluster 也可以跨多 node。
“node down”与“Postgres down”故障面不同:
instance identity 不能只用 IP
IP 可以复用,DNS 可以漂移,hostname 可以被自动化改写。本章组合:
实验中发现一个真实陷阱:工作站 ~/.ssh/config 将四个地址映射到本机不同
转发规则,最初所有连接看起来都是 meta。正式采集强制:
再验证四个不同 machine ID。连接成功不是目标身份成功。
service 是语义,不是 socket
Pigsty 默认 service 可能包括:
官方 Service/Access 记录这些默认映射。端口能建立 TCP 只证明 listener/reachability,不证明:
- primary service 一定落在 current primary;
- replica service 的 freshness;
- pool transaction/session 语义;
- role/database/HBA 正确;
- TLS hostname 验证;
- failover 后客户端恢复。
所以本章 endpoint probe 的解释字段明确写:
cluster name 不应含 current role
推荐稳定层次:
pg-test-primary 可以是 service 名,不应是固定 machine 名。
数据库里的 role 又是另一种 role
避免一句“role 是 replica”同时指:
表格、变量名和 evidence 都写全称。
声明角色与观察角色都要保存
inventory 声明:
观察:
第一次部署时二者应一致。发生 failover 后,inventory 的 bootstrap role 不应 被天真解释为永恒运行角色;第 20 章会定义 drift 语义。
19.5.3 环境、区域、租户与业务命名
命名要编码稳定属性
适合进入名字的:
不适合进入固定 host 名的:
稳定属性让名字在 role change 后继续真实。
一份可扩展命名模型
示例:
名字要满足:
- PostgreSQL identifier 限制;
- DNS label 限制;
- metric label cardinality;
- certificate SAN;
- log/search 可读性;
- automation group syntax;
- rename cost。
environment 是权限与数据边界
常见:
不能只靠名字隔离。还要有:
prod database 和 test database 放在同一个 cluster,通常仍共享 superuser、
WAL、storage、restart、capacity 和 incident blast radius。
region、zone、rack 必须对应可验证故障域
一个 label az-a 不等于独立 zone。登记:
然后为每个 component 画依赖。相同依赖会形成 correlated failure。
本章四台 VM:
所以 failure-domain count 不是四。
tenant 边界不等于 schema 名
租户可能通过:
隔离强度逐步变化,成本也变化。命名中加入 tenant 前,先定义:
- authentication/authorization;
- noisy-neighbor;
- backup/restore granularity;
- key ownership;
- data residency;
- deletion;
- metrics/audit;
- exit/migration。
本章 pg-meta 与 pg-test 是两个 service unit,不是两个 customer tenant。
业务名与技术名需要映射表
不要让应用团队猜:
| 业务对象 | 平台对象 |
|---|---|
| pg36_shop service | pg-test teaching service unit |
| canonical shop DB | future pg36_shop provisioning target |
| control/validation | pg-meta |
| OLTP write endpoint | primary service contract |
| analytical read | offline service contract |
正式 inventory 当前还会创建 template 自带的 test/meta database。它们是
部署示范对象,不表示上卷的 pg36_shop fixture 已迁入这个下卷沙箱。
name registry 要防冲突与复用
登记:
立即复用已退役 cluster 名可能让:
- old DNS/cache 指向新服务;
- backup stanza 混淆;
- monitoring time series 串联;
- client secret 意外生效;
- automation limit 选错目标。
本章拓扑清单
topology.mmd 表达:
它同时画出共享 hypervisor。架构图若只画 database arrows、隐藏共同依赖, 会高估 availability。
命名与拓扑验收
validator 交叉检查:
反例:
通过后的精确结论:
四个地址对应四个同构 Linux guest;
pg-meta与pg-test是两个不同 PostgreSQL system identifier;pg-test有一个 leader 和两个 streaming replica;全部 guest 仍共享一个物理故障域。
上一节:版本与数据库初始化契约 · 返回本章目录 · 下一节:用声明式清单交付两个服务单元 · 查看全书目录 · 查看索引中心