# 计算、内存、存储与网络

LLMS 索引： [llms.txt](/llms.txt)

---

资源规划不是列一张“推荐配置”。它要把 workload 的每种稀缺资源与一个可
观察的饱和点连接起来。

## 19.2.1 CPU 核数、频率、NUMA 与虚拟化 {#item-19-2-1}

### 核数与单核性能解决不同问题

更多核心有利于：

```text
更多并发 backend
parallel query
autovacuum workers
backup compression
replication/application workers
多个实例/服务
```

更强单核性能有利于：

```text
单条不可并行执行路径
短 OLTP tail latency
锁临界区
表达式/PL 执行
单 WAL 路径中的部分工作
```

不能用总 vCPU 数替代 CPU 型号、频率、代际与持续性能。

### SMT 线程不等于物理核心

操作系统报告 32 CPU，可能是：

```text
16 physical cores × 2 SMT
32 physical cores
oversubscribed 32 vCPU
burstable quota
```

基线记录：

```bash
lscpu --json
nproc
cat /sys/fs/cgroup/cpu.max
```

以及 hypervisor/cloud 的：

```text
vCPU entitlement
steal time
credit/burst policy
dedicated/shared
pinning
```

PostgreSQL 并行 worker 数应基于实测吞吐和并发，不按 `nproc` 自动拉满。

### CPU 饱和要看排队

观察：

```text
utilization
runnable queue
steal/throttle
per-process CPU
context switches
frequency
query latency/throughput
```

CPU 100% 但吞吐继续线性增长，和 CPU 70% 但 cgroup throttling/steal 很高，
不是同一问题。

### NUMA 使“总内存/总核心”失去均匀假设

多 socket/NUMA 系统中：

```text
CPU attached to local memory node
remote memory access latency higher
device/interrupt locality differs
kernel allocation can become uneven
```

记录：

```bash
lscpu
numactl --hardware
cat /sys/devices/system/node/node*/meminfo
```

还要确认 BIOS/VM 的 NUMA 暴露、进程/IRQ/pinning 策略。

不要无条件“禁用 NUMA”。小单节点、超大多 socket、VM、容器的最佳策略可能
不同。变更要有 workload 实验。

本章 Vagrant VM 每台只报告一个 NUMA node，因此只能验证采集与同构，不能
形成大型 NUMA 结论。

### 虚拟化要记录资源保证

虚拟机的抽象层可能引入：

```text
CPU oversubscription
steal
memory ballooning
host swap
virtual disk cache
noisy neighbor
live migration pause
shared physical failure
time drift
```

容器还要记录：

```text
CPU quota/cpuset
memory.max
OOM policy
huge page access
ephemeral filesystem
PID/file limits
host network/storage
```

“8 vCPU/32 GiB”若没有 guarantee 与 failure domain，只是一个接口数字。

### 指令集与架构是兼容矩阵的一部分

本章正式 sandbox 是：

```text
architecture=aarch64
OS=Ubuntu 24.04.x
```

所有节点必须相同。生产扩展 package、JIT、compression、加密库与备份恢复
都要覆盖目标架构。不能假设 x86_64 上测试的二进制扩展会在 ARM 恢复目标上
存在。

### CPU 基线不是调优

第 19 章只记录：

```text
logical count
model
NUMA node count
virtualization
kernel/cgroup identity
```

第 26 章测饱和，第 27 章才改变并行和参数。看到核心数不等于知道
`max_parallel_workers_per_gather` 应设多少。

## 19.2.2 内存预算、页缓存与 OOM 边界 {#item-19-2-2}

### PostgreSQL 使用多类内存

```text
shared_buffers
WAL buffers
backend private memory
work_mem per operation
maintenance_work_mem
autovacuum_work_mem
temp_buffers per session
extension/background worker memory
connection/process overhead
OS page cache
kernel/network/filesystem
monitoring/backup/proxy
```

只算 `shared_buffers + max_connections × work_mem` 仍然过度简化。

### 页缓存与 shared buffers 共同工作

PostgreSQL 使用自己的 shared buffer cache，也依赖操作系统 cache。官方
[Resource Consumption](https://www.postgresql.org/docs/18/runtime-config-resource.html)
给出 `shared_buffers` 的起始建议，同时说明 PostgreSQL 还依赖 OS cache。

这意味着：

- 不应把全部 RAM 分给 `shared_buffers`；
- 文件系统/backup/extension 也需要 cache；
- database cache hit 不等于没有底层 I/O；
- VM host cache 还可能再加一层；
- cold/warm benchmark 要定义清楚。

### 乘法内存必须按峰值并发

近似账本：

\[
M_{total}
=
M_{shared}
+ M_{OS}
+ N_{backend}M_{backend}
+ \sum work\ nodes
+ M_{maintenance}
+ M_{other}
+ headroom
\]

`work_mem` 是每 sort/hash 节点的基础预算；并行 worker 与多个节点会放大。

平台应按 role/workload class 设置，而不是一个全局大值：

```text
OLTP runtime
admin migration
offline analytics
maintenance
```

### `max_connections` 是内存与调度承诺

每个 PostgreSQL connection 对应 backend process。大量 idle connection 也有：

```text
process/page table
backend state
locks/proc arrays
TLS/socket
extension/session state
```

大量 active connection 会导致 CPU 排队与 cache 抖动。

规划顺序：

```text
safe active concurrency
  -> backend budget
  -> reserve admin/monitor/replication
  -> pooler server pool
  -> application pool totals
  -> client queue/timeout
```

不是先把 `max_connections` 改成 5000。

### OOM 不是一种可接受的流量控制

当 Linux OOM killer 选择 PostgreSQL 进程：

- backend 被杀；
- postmaster 可能触发所有 backend 重启；
- client 事务中断；
- recovery/checkpoint 增加恢复时间；
- HA 可能触发切换；
- evidence 可能被噪声覆盖。

应使用：

```text
capacity headroom
cgroup/systemd memory boundary
connection/active query budget
work/temp limit
load shedding
monitoring
```

在系统被 OOM 前拒绝或排队。

### overcommit 与 swap 要显式

记录：

```bash
sysctl vm.overcommit_memory
sysctl vm.overcommit_ratio
sysctl vm.swappiness
cat /proc/meminfo
systemctl show ... memory controls
```

策略取决于宿主/容器/工作负载，但未知是不可接受的。

本章 sandbox 要求 guest `SwapTotal=0`，同时承认 macOS host 仍可能压缩/交换
VM 内存；VM 内看到无 swap 不证明物理主机不会产生内存压力。

### Transparent Huge Pages 与显式 huge pages 不同

PostgreSQL 18 官方
[Resource Consumption](https://www.postgresql.org/docs/18/runtime-config-resource.html)
说明 Linux THP 在一些环境中会导致性能下降，目前不鼓励；这与 PostgreSQL
显式 `huge_pages` 不是同一机制。

采集：

```bash
cat /sys/kernel/mm/transparent_hugepage/enabled
cat /sys/kernel/mm/transparent_hugepage/defrag
cat /proc/meminfo | grep Huge
```

Pigsty sandbox 的预期：

```text
THP enabled current=never
THP defrag current=never
explicit hugepage count may remain 0
```

若要启用显式 huge pages，应按 PostgreSQL
[Managing Kernel Resources](https://www.postgresql.org/docs/18/kernel-resources.html)
用 `shared_memory_size_in_huge_pages` 计算并验证，不靠固定百分比模板。

### 内存 floor 与 production sizing 分离

2 GiB 是本章建议的教学下限；正式沙箱对低于该值的三台 VM 记录了
`EX19-LAB-RESOURCE-FLOOR`，而没有把建议偷偷降格。production 仍需依据：

```text
working set
peak connections
query node memory
maintenance overlap
HA/failover state
OS/agent budget
growth
headroom
```

通过 floor 不代表容量 gate 通过。

## 19.2.3 IOPS、吞吐、时延、容量与冗余 {#item-19-2-3}

### 四个存储指标互不等价

```text
IOPS       每秒操作数
throughput 每秒字节
latency    单次完成时间及分布
capacity   可用字节与增长空间
```

小随机 WAL/fsync、索引随机读、大顺序扫描、backup stream 的瓶颈不同。

“云盘 20,000 IOPS”不说明：

- block size；
- read/write mix；
- queue depth；
- P99 latency；
- burst duration；
- fsync/FUA；
- shared cap；
- failure behavior。

### PostgreSQL 的典型 I/O 路径

| 路径 | 特征 |
|---|---|
| WAL write/flush | 小、顺序、durability latency 敏感 |
| checkpoint | 大量脏页写、可能 burst |
| heap/index read | random/sequential 混合 |
| temp spill | 大量短寿命读写 |
| vacuum | 扫描 + index cleanup + WAL |
| backup | 大顺序读 + network + repository write |
| replica | WAL receive/write/replay + data I/O |
| restore | repository read + data write + WAL replay |

需要同时测生产 workload 和维护/故障状态。

### 平均延迟会隐藏 tail

保存：

```text
P50/P95/P99/max
queue depth
utilization
read/write latency
fsync latency
throughput
errors/timeouts
```

交易 commit 通常对 tail latency 更敏感；一次 2 秒 flush 可能制造级联 queue。

### 文件系统与设备语义要完整记录

基线：

```bash
lsblk --json -o NAME,TYPE,SIZE,FSTYPE,MOUNTPOINTS,ROTA,MODEL
findmnt --json
df -B1
mount
```

同时从基础设施层记录：

```text
local/network/block/object
RAID/replication
write cache and power-loss protection
discard/TRIM
snapshot behavior
encryption
IO scheduler
cloud volume class
burst/credit
failure domain
```

数据库内部无法证明底层存储真正持久。

### `fsync=on` 仍依赖硬件诚信

PostgreSQL 发出同步请求后，操作系统/设备必须诚实地把数据持久化。虚假 write
cache acknowledgment 会破坏 WAL 设计前提。

验收需要：

- 合格存储/云服务语义；
- power-loss protection；
- 厂商/基础设施保证；
- 故障测试与恢复；
- checksums/备份/取证作为纵深。

不要用 `fsync=off` 解决 production latency；那是在更改持久性合同。

### 容量要给多个并发动作留空间

磁盘不能规划到 95% 常态：

```text
database growth
index build/reindex
VACUUM FULL/table rewrite
major upgrade copy/link strategy
base backup staging
WAL/archive backlog
logical slot retention
temp spill
log/metrics
filesystem reserve
```

headroom 应按最坏的已批准维护/故障动作计算。

### redundancy 不等于 backup

RAID/云盘副本：

```text
覆盖部分设备故障
不覆盖误删、逻辑错误、很多软件损坏
```

PostgreSQL replica：

```text
覆盖服务成员故障
复制已提交错误
```

backup/PITR：

```text
提供历史恢复
依赖仓库、WAL、密钥、过程与时间
```

三者互补。

### 检查 checksum，但不要过度解读

PostgreSQL 18
[`initdb`](https://www.postgresql.org/docs/18/app-initdb.html)
默认启用 data checksums，可用 `--no-data-checksums` 关闭。checksum 能检测一类
页面静默损坏；它不纠正错误，也不覆盖：

```text
WAL/archive completeness
application logical errors
所有内存/网络/文件损坏
backup recoverability
replica independence
```

本章要求每个成员 `data_checksums=on`，并把实际检测与修复留给第 28/35 章。

### Vagrant 存储只能做流程验证

本章采集 root 与 `/pg` mount、总量/free、类型/options，但明确例外：

```text
EX19-VIRTUAL-STORAGE
```

它不能为 production IOPS、P99、endurance、power-loss 或冗余签字。

## 19.2.4 时钟、DNS、带宽、防火墙与故障域 {#item-19-2-4}

### 时钟是分布式证据的坐标

时钟影响：

```text
TLS/certificate
日志关联
监控窗口
lease/election
backup/PITR target
业务时间
token expiry
incident timeline
```

每台记录：

```bash
timedatectl show
chronyc tracking
chronyc sources -v
```

验收：

```text
timezone=UTC or Etc/UTC
NTPSynchronized=yes
source/offset within policy
```

“时间看起来差不多”不够。

数据库通常用 UTC 保存绝对时刻；用户展示时再按业务时区转换。OS 日志也应
统一可换算。

### DNS 是服务依赖

记录：

```text
authoritative zone
resolver path
TTL
negative cache
search domain
split-horizon
failover/update authority
monitoring
```

不要让 PostgreSQL 成员依赖一个单点、不可观察的外部 resolver。

`/etc/hosts` 适合固定 sandbox，生产服务发现要有 owner 与变更流程。

### IP、hostname、service name 分层

```text
node identity     node-1 / host UUID
instance identity pg-test-2
cluster identity  pg-test
service identity  pg-test-primary / replica / offline
business identity pg36_shop
```

客户端连 service，不连“当前 primary 的 IP”。IP 可以变，service 语义应
稳定。

### 带宽要算复制与恢复

网络预算：

```text
client request/response
streaming WAL
base backup/rebuild
archive upload
restore download
monitor/log
external CDC/export
package deployment
```

恢复或新副本同步可能是最大流量。

若：

\[
rebuild\ time \approx \frac{data\ bytes}{effective\ bandwidth}
\]

还要加 checksum、compression、I/O、WAL catch-up 与争用。链路标称带宽不是
effective。

### 网络延迟进入同步提交

同步副本确认需要跨 failure domain 往返。距离越远，commit latency 越高；
距离太近，则可能不覆盖目标故障。

所以同步位置不是“同城最好”或“跨区最好”，而是 RPO、延迟、可用性和故障域
共同取舍。第 20 章实测。

### 防火墙从允许关系生成

不要先“关防火墙排障”，再忘记打开。建立 flow matrix：

| source | destination | port/protocol | purpose | auth |
|---|---|---|---|---|
| app | PG service | TCP | business SQL | TLS + role |
| PG member | PG member | TCP | streaming | replication role |
| Patroni | etcd | TCP/TLS | DCS | cert/credential |
| LB | Patroni REST | TCP | role health | network policy |
| backup | repository | TCP/TLS | archive/restore | scoped secret |
| monitoring | exporters | TCP | metrics | network/auth |
| admin | hosts | SSH | control | admin identity |

规则要双向核对：inventory 声明、主机 firewall、cloud security group、实际
probe。

Pigsty 4.5
[Node Parameters](https://pigsty.io/docs/node/param/)
说明其 firewall 模式与 intranet/public 策略；具体默认仍要从目标配置与主机
事实确认。

### “四台机器”不等于四个故障域

故障域清单：

```text
process
instance/VM
host/hypervisor
disk/controller/storage service
rack/power
switch/network
zone/datacenter
region
DNS/IAM/control plane
operator/configuration
backup repository/key
```

两个 node ID 可能共享除进程外的所有域。

本章四个 machine-id 确实不同，但它们共享：

```text
one physical laptop
one hypervisor
one power source
one physical storage
one host network
```

所以 validator 同时要求：

```text
machine identities distinct
EX19-SHARED-HYPERVISOR present
production SLO claim false
```

只通过前一项会制造错误结论。

### DCS 与 backup 也有故障域

三节点 PostgreSQL + 单节点 etcd：

```text
data members=3
DCS members=1
```

不是完整生产 HA。

备份放在同一 control VM/physical host：

```text
backup copy exists
independent disaster copy does not
```

拓扑图必须画控制与恢复依赖，不只画 PostgreSQL。

### 本节的验收产物

主机采集器
[`remote_host_facts.py`](/labs/ch19/remote_host_facts.py)
只读输出：

```text
hashed machine identity
OS/kernel/architecture/virtualization
CPU/NUMA
memory/swap/THP/overcommit
mount/free space
clock/NTP
addresses/DNS/firewall/listening ports
service and package versions
```

它记录事实，不自动执行任何 sysctl、mount 或 firewall 调优。

---

[上一节：先写服务需求](../01/) · [返回本章目录](../) · [下一节：操作系统与主机基线](../03/) ·
[查看全书目录](/toc/) · [查看索引中心](/indexes/)
