如果您只有一分钟,请记住这张图:
flowchart TB
subgraph Cluster["🏢 集群 (Cluster): pg-test"]
direction TB
ClusterNote["自治业务单元,顶级命名空间"]
subgraph Instances["💻 实例 (Instance)"]
direction LR
I1["pg-test-1<br/>(primary)"]
I2["pg-test-2<br/>(replica)"]
I3["pg-test-3<br/>(replica)"]
end
subgraph Nodes["🖥️ 节点 (Node)"]
direction LR
N1["10.10.10.11"]
N2["10.10.10.12"]
N3["10.10.10.13"]
end
subgraph Services["🌐 服务 (Service)"]
S1["pg-test-primary:5433 → 读写请求 → pg-test-1"]
S2["pg-test-replica:5434 → 只读请求 → pg-test-2, pg-test-3"]
S3["pg-test-offline:5438 → 分析查询 → pg-test-3"]
end
Instances --> |1:1 部署| Nodes
end
Summary["📋 一段配置,自动生成所有标识、服务和监控标签"]
核心价值:用四个简单的概念(集群、实例、服务、节点)描述任意复杂的数据库拓扑。一次定义,处处一致:配置、监控、日志、告警自动关联。
本章内容
| 章节 | 说明 | 核心问题 |
|---|---|---|
| 实体关系 | 四种核心实体的定义与相互关系 | 集群、实例、服务、节点是什么? |
| 身份标识 | 命名规范与衍生标识符设计 | 如何给数据库起名字? |
为什么需要逻辑模型?
没有模型的困境
flowchart TB
subgraph Problems["❌ 命名混乱的日常"]
direction TB
P1["❌ 名称随意<br/>主机名:db01、database-server、pg_prod_1<br/>实例名:postgres、postgresql、pg-instance<br/>服务名:pg、pgsql、database、5432<br/>谁也记不住,每次都要查文档"]
P2["❌ 关联困难<br/>这个告警是哪个集群的?<br/>这条日志对应哪个实例?<br/>这个指标来自哪台机器?<br/>排查问题像破案,信息碎片化"]
P3["❌ 扩容混乱<br/>新加的机器叫什么名字?<br/>序号从几开始?<br/>和现有命名冲突怎么办?"]
end
Pigsty 的解决方案
flowchart TB
subgraph Solutions["✅ 统一逻辑模型"]
direction TB
S1["✅ 命名一致<br/>集群名:pg-order、pg-user(语义化,全局唯一)<br/>实例名:pg-order-1、pg-order-2(集群名+序号)<br/>服务名:pg-order-primary、pg-order-replica(自动生成)<br/>规则简单,看名知义"]
S2["✅ 自动关联<br/>监控标签:cls=pg-order, ins=pg-order-1<br/>日志标签:自动携带集群和实例信息<br/>告警通知:明确标识问题来源<br/>一个查询找到所有相关信息"]
S3["✅ 规范扩容<br/>新实例:pg-order-4(序号递增,自动命名)<br/>新服务:pg-order-standby(自定义服务,规范后缀)<br/>无冲突,可预测"]
end
四种核心实体
实体概览
flowchart TB
subgraph ClusterEntity["🏢 集群 (Cluster)"]
C1["自治的业务服务单元<br/>顶级命名空间,衍生出其他所有名称<br/>配置管理、监控告警、服务发现的基本单位<br/>例如:pg-order、pg-user、pg-meta"]
end
ClusterEntity --> InstanceEntity & ServiceEntity & NodeEntity
subgraph InstanceEntity["💻 实例 (Instance)"]
I1["单个数据库进程<br/>明确的复制角色<br/>pg-order-1"]
end
subgraph ServiceEntity["🌐 服务 (Service)"]
S1["能力的命名抽象<br/>HAProxy 暴露<br/>pg-order-primary"]
end
subgraph NodeEntity["🖥️ 节点 (Node)"]
N1["硬件资源抽象<br/>IP 地址标识<br/>10.10.10.11"]
end
实体对比
| 实体 | 定义 | 标识方式 | 数量 | 示例 |
|---|---|---|---|---|
| 集群 | 一组复制关联的实例 | 集群名 | 1 | pg-test |
| 实例 | 单个数据库服务器 | 集群名-序号 | 1+ | pg-test-1 |
| 服务 | 流量路由的抽象 | 集群名-角色 | 4+ | pg-test-primary |
| 节点 | 运行实例的机器 | IP 地址 | 1+ | 10.10.10.11 |
最小配置示例
只需三个参数,定义完整集群:
# pigsty.yml
pg-test: # ← 集群名
hosts:
10.10.10.11: { pg_seq: 1, pg_role: primary } # ← 节点+实例
10.10.10.12: { pg_seq: 2, pg_role: replica } # ← 节点+实例
10.10.10.13: { pg_seq: 3, pg_role: replica } # ← 节点+实例
vars:
pg_cluster: pg-test # ← 必填:集群标识
三个必填参数
| 参数 | 层级 | 说明 | 约束 |
|---|---|---|---|
pg_cluster |
集群 | 集群名称 | [a-z][a-z0-9-]*,不含点号 |
pg_seq |
实例 | 实例序号 | 集群内唯一正整数 |
pg_role |
实例 | 实例角色 | primary/replica/offline/delayed |
自动生成的标识
从上述配置自动衍生:
| 实体 | 标识 | 说明 |
|---|---|---|
| 集群 | pg-test |
配置文件中显式定义 |
| 实例 | pg-test-1 |
${pg_cluster}-${pg_seq} |
| 实例 | pg-test-2 |
${pg_cluster}-${pg_seq} |
| 实例 | pg-test-3 |
${pg_cluster}-${pg_seq} |
| 服务 | pg-test-primary |
自动创建,端口 5433 |
| 服务 | pg-test-replica |
自动创建,端口 5434 |
| 服务 | pg-test-default |
自动创建,端口 5436 |
| 服务 | pg-test-offline |
自动创建,端口 5438 |
| 节点 | pg-test-1 |
主机名默认等于实例名 |
实例角色
角色类型
flowchart TB
subgraph Primary["🔴 primary - 主库,有且仅有一个"]
P1["唯一可写入的实例<br/>产生 WAL 日志,其他实例复制<br/>承载读写业务流量"]
end
Primary --> |复制| Replica
subgraph Replica["🟡 replica - 从库,0到多个"]
R1["实时同步主库数据<br/>承载只读业务流量<br/>主库故障时可提升为新主库"]
end
subgraph Offline["🔵 offline - 离线库,0到多个"]
O1["不承载在线业务流量<br/>用于 ETL、数据分析、备份等<br/>避免慢查询影响线上业务"]
end
subgraph Delayed["🟣 delayed - 延迟库,0到多个"]
D1["延迟复制主库数据(如延迟 1 小时)<br/>用于误操作恢复,提供时间窗口<br/>不承载在线流量"]
end
角色对比
| 角色 | 可读 | 可写 | 承载流量 | 数量 | 典型用途 |
|---|---|---|---|---|---|
primary |
✅ | ✅ | 读写 | 1 | 核心业务 |
replica |
✅ | ❌ | 只读 | 0+ | 读扩展 |
offline |
✅ | ❌ | 离线 | 0+ | ETL/分析 |
delayed |
✅ | ❌ | 无 | 0+ | 误操作恢复 |
服务抽象
默认服务
flowchart TB
Client["🖥️ 客户端"] --> HAProxy
subgraph HAProxy["🔀 HAProxy"]
direction TB
S1[":5433 pg-test-primary<br/>目标: 主库 (role=primary)<br/>用途: 读写业务、OLTP"]
S2[":5434 pg-test-replica<br/>目标: 从库 (role=replica)<br/>用途: 只读查询、读扩展"]
S3[":5436 pg-test-default<br/>目标: 主库 (直连,绕过 Pgbouncer)<br/>用途: 管理操作、DDL、大事务"]
S4[":5438 pg-test-offline<br/>目标: 离线库 (role=offline)<br/>用途: ETL、分析、慢查询"]
end
subgraph Advantages["✅ 服务优势"]
A1["应用使用服务名连接,无需知道具体实例"]
A2["主库故障切换后,流量自动路由到新主库"]
A3["读写分离天然实现,无需修改应用代码"]
end
连接示例
# 读写业务(连接主库)
psql postgres://dbuser_app:password@10.10.10.11:5433/mydb
# 只读查询(负载均衡到从库)
psql postgres://dbuser_app:password@10.10.10.11:5434/mydb
# 管理操作(直连主库)
psql postgres://dbuser_dba:password@10.10.10.11:5436/mydb
# ETL 分析(连接离线库)
psql postgres://dbuser_etl:password@10.10.10.11:5438/mydb
监控集成
标签体系
监控系统自动使用身份参数作为标签:
# 指标示例
pg_up{cls="pg-test", ins="pg-test-1", ip="10.10.10.11", job="pgsql"} 1
pg_up{cls="pg-test", ins="pg-test-2", ip="10.10.10.12", job="pgsql"} 1
pg_up{cls="pg-test", ins="pg-test-3", ip="10.10.10.13", job="pgsql"} 1
| 标签 | 来源 | 说明 |
|---|---|---|
cls |
pg_cluster |
集群名,用于集群级聚合 |
ins |
pg_cluster-pg_seq |
实例名,用于实例级查询 |
ip |
节点 IP | 节点地址,用于主机关联 |
job |
固定值 | pgsql 或 pgrds |
查询示例
# 查看集群 pg-test 的所有实例状态
pg_up{cls="pg-test"}
# 查看实例 pg-test-1 的连接数
pg_stat_activity_count{ins="pg-test-1"}
# 聚合集群总连接数
sum(pg_stat_activity_count{cls="pg-test"})
# 查看复制延迟
pg_replication_lag_seconds{cls="pg-test", ins=~"pg-test-[2-3]"}
命名最佳实践
集群命名
flowchart TB
subgraph BasicFormat["📝 推荐格式:pg-{业务}"]
B1["pg-order → 订单服务"]
B2["pg-user → 用户服务"]
B3["pg-payment → 支付服务"]
end
subgraph EnvFormat["🏷️ 带环境前缀:pg-{环境}-{业务}"]
E1["pg-prod-order → 生产订单库"]
E2["pg-stag-order → 预发订单库"]
E3["pg-dev-order → 开发订单库"]
end
subgraph Rules["📋 规则约束"]
R1["✅ 小写字母、数字、连字符"]
R2["✅ 必须以字母开头"]
R3["❌ 不能包含点号、下划线、大写字母"]
R4["📐 正则:[a-z][a-z0-9-]*"]
end
序号分配
| 原则 | 说明 |
|---|---|
| 不要复用 | 实例销毁后,序号应保留,避免混淆历史数据 |
| 预留空间 | 为将来扩容预留序号范围 |
| 记录映射 | 维护序号与用途的映射文档 |
| 从 1 开始 | 序号从 1 开始,表示第一个实例 |
接下来
深入了解逻辑模型的细节:
相关话题: