# Pigsty 的资源模型

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

---

上一节把数据库平台拆成一组通用职责。本节只做一件事：把这些职责映射到 Pigsty v4.5 的实体、组件和证据源。记住映射比背命令重要，因为端口、界面和组件版本会变化，而“谁负责数据、谁负责角色判断、谁负责路由”必须始终说得清。

## 1.5.1 节点、集群、实例与服务 {#item-1-5-1}

Pigsty 的 PGSQL 模块使用四个核心实体组织 PostgreSQL：

| 实体 | 定义 | `pg-meta` 单节点示例 | 不能混淆为 |
|---|---|---|---|
| 节点（node） | 运行 Linux 与 systemd 的计算资源 | 一台 VM 或裸机 | PostgreSQL 数据库 |
| 实例（instance） | 节点上的一套 PostgreSQL 服务器与数据目录 | `pg-meta-1` | 整个业务集群 |
| 集群（cluster） | 由主备关系组织的自治业务单元 | `pg-meta` | PostgreSQL 官方语义中的 database cluster |
| 服务（service） | 按角色和用途选择实例的稳定访问抽象 | `pg-meta-primary` | 固定某台实例 |

Pigsty 默认采用节点与 PostgreSQL 实例 1:1 的独占部署模型，因此节点名经常借用实例名；这是 Pigsty 的部署约定，不是 PostgreSQL 限制。`pg_cluster`、`pg_seq` 和 `pg_role` 三个身份参数构成最小声明：

```yaml
pg-meta:
  hosts:
    10.10.10.10: { pg_seq: 1, pg_role: primary }
  vars:
    pg_cluster: pg-meta
```

由此可以推导：

```text
节点：10.10.10.10（默认命名可为 pg-meta-1）
实例：pg-meta-1
集群：pg-meta
服务：pg-meta-primary / pg-meta-replica / pg-meta-default / pg-meta-offline
```

配置中的 `pg_role: primary` 表示初始化或编排意图，不是永远不变的运行角色。多节点集群发生切换后，主库可以从 `pg-meta-1` 变成其他实例，而实例编号不变。服务名表达访问意图，也不应跟着当前主实例改名。

在 Pigsty 管理节点的安装目录中，用只读命令观察解析后的配置范围：

```bash
cd ~/pigsty

# 只显示分组与主机关系，不输出包含密码的完整变量
ansible-inventory --graph

# 只从源文件定位非敏感身份字段；动态清单环境应改查相应 CMDB
grep -nE 'pg-meta:|pg_cluster:|pg_seq:|pg_role:' pigsty.yml
```

不要把完整 `ansible-inventory --list` 直接贴进工单或书稿，它可能包含密码、令牌和内部地址。证据包只采集解决当前问题所需的字段。

单节点 L1 会让四种服务最终落到同一台节点甚至同一个 PostgreSQL 实例，但实体仍然不同。就像一位工程师可以兼任开发、值班和发布审批，职责名称相同不意味着角色边界消失。

## 1.5.2 PostgreSQL、Patroni、PgBouncer 与 HAProxy 的职责 {#item-1-5-2}

一条默认生产读写连接的路径是：

```text
客户端
  → HAProxy :5433
  → 当前主实例上的 PgBouncer :6432
  → PostgreSQL :5432
```

组件之间不是相互替代，而是逐层收窄职责：

| 组件 | 核心职责 | 它不负责什么 | 本章证据 |
|---|---|---|---|
| PostgreSQL | SQL、事务、存储、WAL、复制、权限和原生状态 | 不提供跨主机的唯一高可用控制面或统一服务入口 | SQL、系统目录、日志 |
| Patroni | 管理 PostgreSQL 生命周期，以 DCS 协调角色、配置和故障转移，并提供健康接口 | 不执行应用 SQL，不承担连接池 | `pg list`、REST 健康状态、Patroni 日志 |
| PgBouncer | 复用客户端到 PostgreSQL 的连接，限制和缓冲连接压力 | 不保存业务数据，不决定谁应成为主库 | 管理控制台、连接池指标、日志 |
| HAProxy | 暴露 TCP 服务端口，根据健康检查把流量路由到合格后端 | 不理解 SQL 事务，不复制数据 | 后端状态、端口、HAProxy 指标与配置 |

在高可用集群中，Patroni 通常使用 etcd 之类的分布式配置存储（DCS）协调领导者信息。HAProxy 请求 Patroni 健康接口判断实例角色，再把 `5433` 流量送往主库的 PgBouncer。PgBouncer 最后通过本地连接进入 PostgreSQL。

Pigsty v4.5 的默认入口如下，均可配置：

| 端口 | 入口 | 默认目标 |
|---:|---|---|
| `5432` | PostgreSQL | 当前这台实例，直连 |
| `6432` | PgBouncer | 当前这台实例的连接池 |
| `5433` | primary 服务 | 主库 PgBouncer，生产读写 |
| `5434` | replica 服务 | 备库 PgBouncer，生产只读路由 |
| `5436` | default 服务 | 主库 PostgreSQL，管理直连 |
| `5438` | offline 服务 | 离线备库 PostgreSQL |

“默认目标”必须结合配置阅读。例如 `pg_default_service_dest` 可以让 primary/replica 服务绕过 PgBouncer。不要仅凭端口号推断实际路径。

在管理节点上查看控制面状态：

```bash
# R0：列出集群成员、角色和复制状态
pg list pg-meta
```

在数据库中从另一侧复核：

```sql
SELECT
    pg_is_in_recovery() AS in_recovery,
    current_setting('port') AS postgres_port,
    inet_server_addr() AS server_addr,
    inet_server_port() AS accepted_port;
```

若 `pg list` 报告 Leader，而 SQL 的 `pg_is_in_recovery()` 为 `true`，不要挑一个自己喜欢的结果继续操作。先停止角色相关变更，确认两条命令是否观察了同一集群、同一实例和同一时刻，再检查 Patroni 与 PostgreSQL 日志。配置标签、控制面判断和内核运行状态不一致，本身就是需要处理的事件。

本节暂不演练切换、连接池模式或代理重载；它们分别属于 ch20《高可用拓扑与容灾目标》和 ch22《服务接入、连接池与路由》。

## 1.5.3 配置清单、运行状态与监控事实分别来自哪里 {#item-1-5-3}

Pigsty 环境至少存在三类事实源：

### 配置清单：系统应当是什么

默认静态清单是 `~/pigsty/pigsty.yml`，也可以使用动态 inventory 或 CMDB。它声明节点、集群、初始角色、数据库、用户、服务和参数。清单适合回答“期望如何配置”，不能单独证明变更已经执行并生效。

### 运行状态：系统现在是什么

运行状态分散在各组件中：

- PostgreSQL：SQL、系统目录、统计视图和日志；
- Patroni：成员与角色状态、DCS 信息、健康接口和日志；
- PgBouncer：连接池状态、管理控制台和日志；
- HAProxy：服务后端、健康检查、运行配置和日志；
- systemd 与主机：进程、端口、文件、资源和服务状态。

例如，“当前谁是主库”首先要看 PostgreSQL 与 Patroni 的实时状态，而不是初始化清单中的 `pg_role` 标签。

### 监控事实：系统在一段时间内发生了什么

Pigsty 的采集系统把 PostgreSQL、主机、组件和日志事实转换成带标签的时间序列与日志流。常见身份标签包括：

- `cls`：集群；
- `ins`：实例；
- `ip`：节点地址；
- `job`：采集任务或日志来源；
- `datname`、`relname`、`idxname`：数据库内部对象。

监控适合回答趋势、持续时间和事件先后，但它仍可能受采集间隔、标签错误、查询权限和数据保留影响。面板显示“主库”时，应能追到指标标签与原生 SQL；SQL 显示瞬时正常时，也不能据此否认五分钟前的告警。

建立一张证据优先级表：

| 要回答的问题 | 首选运行证据 | 配置证据 | 历史证据 |
|---|---|---|---|
| 当前连接进入哪个数据库和角色？ | `current_database()`、`session_user` | 连接配置 | 连接日志 |
| 当前实例是主库还是备库？ | `pg_is_in_recovery()` + Patroni 状态 | 初始 `pg_role` | 角色指标、切换日志 |
| 某参数现在是否生效？ | `pg_settings` | `pigsty.yml`／Patroni 配置 | 配置变更与重启记录 |
| 某服务把流量送到哪里？ | HAProxy 后端 + SQL 落点 | 服务定义 | 代理指标与日志 |
| 过去是否发生连接尖峰？ | 当前活动只能辅助 | 连接上限配置 | 连接时间序列、日志 |

### 实战：生成 L1 资源快照

在管理节点执行：

```bash
cd ~/pigsty

{
  printf 'captured_at=%s\n' "$(date -Is)"
  printf 'host=%s\n' "$(hostname -f 2>/dev/null || hostname)"
  printf 'pigsty_source=%s\n' "$(git describe --tags --always 2>/dev/null || printf unknown)"
  printf '%s\n' '--- inventory graph ---'
  ansible-inventory --graph
  printf '%s\n' '--- cluster runtime ---'
  pg list pg-meta
} > pg36-l1-platform.txt
```

这段脚本只采集身份与拓扑，不输出完整变量。若环境不是 Git 安装，`pigsty_source=unknown` 是有效结果，随后应从发行包或发布记录补充版本，而不是编造标签。

在数据库端另存原生快照：

```bash
psql -X "$PG36_BOOTSTRAP_URL" -A -t -c "
SELECT jsonb_build_object(
  'captured_at', clock_timestamp(),
  'database', current_database(),
  'user', current_user,
  'server_addr', inet_server_addr(),
  'server_port', inet_server_port(),
  'version', current_setting('server_version'),
  'in_recovery', pg_is_in_recovery()
);" > pg36-l1-postgres.json
```

两份文件共同构成证据：一份描述平台，一份描述 PostgreSQL。提交或分享前检查是否含有内部地址、用户名或其他不应公开的信息；密码和令牌在任何情况下都不应进入证据包。

### 本节验收

你应当能够从 L1 环境指出：

- 哪个名字是节点、实例、集群和服务；
- `5432`、`6432`、`5433` 各由哪个组件接收；
- 配置清单、`pg list`、SQL 与监控分别回答什么问题；
- 当这些证据冲突时，为什么“重新运行自动化让它一致”不是安全的第一动作。

## 参考资料

- [Pigsty v4.5：PGSQL 集群模型](https://pigsty.io/docs/concept/model/pgsql/)
- [Pigsty v4.5：PGSQL 架构](https://pigsty.io/docs/concept/arch/pgsql/)
- [Pigsty v4.5：服务与接入](https://pigsty.io/docs/pgsql/service/)
- [Pigsty v4.5：发布注记](https://pigsty.io/docs/about/release/)

---

[上一节：从数据库实例到数据库服务](../04/) · [返回本章目录](../) · [下一节：最小 psql 生存卡](../06/) ·
[查看全书目录](/toc/) · [查看索引中心](/indexes/)
