基本概念
Pigsty中涉及到的基本概念:层次结构、高可用,系统架构,等等……
Architecture Overview [DRAFT]
Entity and Concept

Overview
Take standard demo cluster as an example, this cluster consist of four nodes: meta
, node-1
, node-2
, node-3
.

- 节点运行有
postgres
, pgbouncer
, patroni
, haproxy
, node_exporter
, pg_exporter
, pgbouncer_exporter
,consul
等服务
- 集群中有两套数据库集群:
pg-meta
与 pg-test
。其中pg-test
为一主两从结构,pg-meta
为单主结构。
meta
节点上运行有基础设施服务:nginx
, repo
, ntp
, dns
, consul server/etcd
, prometheus
, grafana
, alertmanager
等
- 接入层使用DNS与VIP对外暴露服务,将流量导引至对应的服务节点(可选)。
Service Overview
Pigsty provides multiple ways to connect to database:
- L2: via virtual IP address that are bond to primary instance
- L4: via haproxy load balancer that runs symmetrically on all nodes among cluster
- L7: via DNS (
pg-test
, primary.pg-test
, replica.pg-test
)
And multiple ways to route (read-only/read-write) traffic:
- Distinguish primary and replica service by DNS (
pg-test
, pg-test-primary
, pg-test-replica
)
- Distinguish primary and replica service by Port (5433 for primary, 5434 for replica)
- Direct instance access
- Smart Client (
target_session_attrs=read-write
)
Lot’s of configurable parameters items, refer to Proxy Configuration Guide for more detail.

Database Access Guide provides information about how to connect to database.
1 - 可观测性
介绍PostgreSQL的可观测性
Observability / 可观测性
第一个问题是Observability,可观测性。
那么,什么是可观测性呢?对于这样的问题,列举定义是枯燥乏味的,让我们直接以Postgres本身为例。
这张图,显示了Postgres本身的可观测性。PostgreSQL 提供了丰富的观测接口,包括系统目录,统计视图,辅助函数。 (简单介绍)
这些都是我们可以观测的对象,我能很荣幸地宣称,这里列出的信息全部被Pigsty所收录,并且通过精心的设计,将晦涩的指标数据,转换成了人类可以轻松理解的Insight
下面让我们以一个最经典的例子来深入探索可观测性: pg_stat_statements ,这是Postgres官方提供的统计插件,可以暴露出数据库中执行的每一类查询的详细统计指标。与图中Query Planning和Execution相对应

2 - 高可用
介绍Pigsty提供的高可用
一、意义
- 显著提高系统整体可用性,提高RTO与RPO水平。
- 极大提高运维灵活性与可演化性,可以通过主动切换进行滚动升级,灰度停机维护。
- 极大提高系统可维护性,自动维护域名,服务,角色,机器,监控等系统间的一致性。显著减少运维工作量,降低管理成本
二、目标
当我们在说高可用时,究竟在说什么?Several nines ?
说到底,对于传统单领导者数据库来说,核心问题是就是故障切换,是领导权力交接的问题。
目标层次
- L0,手工操作,完全通过DBA人工介入,手工操作完成故障切换(十几分钟到小时级)
- L1,辅助操作,有一系列手工脚本,完成选主,拓扑切换,流量切换等操作(几分钟)
- L2,半自动化,自动检测,人工决策,自动操作。(1分钟)
- L3,全自动化:自动检测,自动决策,自动操作。(10s)
关键指标
- 允许进行日常Failover与Switchover操作,不允许出现脑裂。
- 无需客户端介入,提供代理切换机制,基于流复制,不依赖特殊硬件。
- 域名解析,VIP流量切换,服务发现,监控适配都需要与自动故障切换对接,做到自动化。
- 支持PG 10~12版本与CentOS 7,不会给云原生改造埋坑。
交付方式
- 沙盒模型,展示期待的部署架构与状态
- 调整方案,说明如何将现有环境调整至理想状态。
三、效果
场景演示
集群状况介绍
- 主库URL:
postgres://dbuser_test:dbuser_test@testdb:5555/testdb
- 从库URL:
postgres://dbuser_test:dbuser_test@testdb:5556/testdb
HA的两个核心场景:
故障切换的四个核心问题:
- 故障检测(Lease, TTL,Patroni向DCS获取Leader Key)
- Fencing(Patroni demote,kill PG进程,或通过Watchdog直接重启)
- 拓扑调整(通过DCS选主,其他从库从DCS获取新主库信息,修改自身复制源并重启生效)
- 流量切换(监听选主事件,通知网络层修改解析)
Patroni原理:故障检测
- 基于DCS判定
- 心跳包保活
- Leader Key Lease
- 秦失其鹿,天下共逐之。
Patroni原理:Fencing
Patroni原理:选主
- The king is dead, long live the king
- 先入关者王
流量切换原理
搭建环境
https://github.com/Vonng/pigsty
五、细节,问题,与风险
场景演示
- Switchover
- Standby Down
- Patroni Down
- Postgres Down
- Accidentally Promote
- Primary Down
- Failover
- DCS Down
- DCS Service Down
- DCS Primary Client Down
- DCS Standby Client Down
- Fencing And corner cases
- Standby Cluster
- Sync Standby
- Takeover existing cluster
问题探讨
关键问题:DCS的SLA如何保障?
==在自动切换模式下,如果DCS挂了,当前主库会在retry_timeout 后Demote成从库,导致所有集群不可写==。
作为分布式共识数据库,Consul/Etcd是相当稳健的,但仍必须确保DCS的SLA高于DB的SLA。
解决方法:配置一个足够大的retry_timeout
,并通过几种以下方式从管理上解决此问题。
- SLA确保DCS一年的不可用时间短于该时长
- 运维人员能确保在
retry_timeout
之内解决DCS Service Down的问题。
- DBA能确保在
retry_timeout
之内将关闭集群的自动切换功能(打开维护模式)。
可以优化的点? 添加绕开DCS的P2P检测,如果主库意识到自己所处的分区仍为Major分区,不触发操作。
关键问题:HA策略,RPO优先或RTO优先?
可用性与一致性谁优先?例如,普通库RTO优先,金融支付类RPO优先。
普通库允许紧急故障切换时丢失极少量数据(阈值可配置,例如最近1M写入)
与钱相关的库不允许丢数据,相应地在故障切换时需要更多更审慎的检查或人工介入。
关键问题:Fencing机制,是否允许关机?
在正常情况下,Patroni会在发生Leader Change时先执行Primary Fencing,通过杀掉PG进程的方式进行。
但在某些极端情况下,比如vm暂停,软件Bug,或者极高负载,有可能没法成功完成这一点。那么就需要通过重启机器的方式一了百了。是否可以接受?在极端环境下会有怎样的表现?
关键操作:选主之后
选主之后要记得存盘。手工做一次Checkpoint确保万无一失。
关键问题:流量切换怎样做,2层,4层,7层
- 2层:VIP漂移
- 4层:Haproxy分发
- 7层:DNS域名解析
关键问题:一主一从的特殊场景
- 2层:VIP漂移
- 4层:Haproxy分发
- 7层:DNS域名解析
切换流程细节
主动切换流程
假设集群包括一台主库P,n台从库S,所有从库直接挂载在主库上。
- 检测:主动切换不需要检测故障
- 选主:人工从集群中选择复制延迟最低的从库,将其作为候选主库(C)andidate。
- 拓扑调整
- 修改主库P配置,使得C成为同步从库,使切换RTO = 0。
- 重定向其他从库,将其
primary_conninfo
指向C,作为级连从库,滚动重启生效。
- 流量切换:需要快速自动化执行以下步骤
- Fencing P,停止当前主库P,视流量来源决定手段狠辣程度
- PAUSE Pgbouncer连接池
- 修改P的HBA文件并Reload
- 停止Postgres服务。
- 确认无法写入
- Promote C:提升候选主库C为新主库
- 移除standby.signal 或 recovery.conf。执行promote
- 如果Promote失败,重启P完成回滚。
- 如果Promote成功,执行以下任务:
- 自动生成候选主库C的新角色域名:
.primary.
- 调整集群主库域名/VIP解析:
primary.
,指向C
- 调整集群从库域名/VIP解析:
standby.
,摘除C(一主一从除外)
- 根据新的角色域名重置监控(修改Consul Node名称并重启)
- Rewind P:(可选)将旧主库Rewind后作为新从库
- 运行
pg_rewind
,如果成功则继续,如果失败则直接重做从库。
- 修改
recovery.conf(12-)|postgresql.auto.conf(12)
,将其primary_conninfo
指向C
- 自动生成P的新角色域名:
< max(standby_sequence) + 1>.standby.
- 集群从库域名/VIP解析变更:
standby.
,向S中添加P,承接读流量
- 根据角色域名重置监控
自动切换流程
自动切换的核心区别在于主库不可用。如果主库可用,那么完全同主动切换一样即可。
自动切换相比之下要多了两个问题,即检测与选主的问题,同时拓扑调整也因为主库不可用而有所区别。
- 检测
(网络不可达,端口拒绝连接,进程消失,无法写入,多个从库上的WAL Receiver断开)
- 实现:检测可以使用主动/定时脚本,也可以直接访问
pg_exporter
,或者由Agent定期向DCS汇报。
- 触发:主动式检测触发,或监听DCS事件。触发结果可以是调用中控机上的HA脚本进行集中式调整,也可以由Agent进行本机操作。
- 选主
- Fencing P:同手动切换,因为自动切换中主库不可用,无法修改同步提交配置,因此存在RPO > 0 的可能性。
- 遍历所有可达从库,找出LSN最大者,选定为C,最小化RPO。
- 流量切换:需要快速自动化执行以下步骤
- Promote C:提升候选主库C为新主库
- 移除standby.signal 或 recovery.conf。执行promote
- 自动生成候选主库C的新角色域名:
.primary.
- 调整集群主库域名/VIP解析:
primary.
,指向C
- 调整集群从库域名/VIP解析:
standby.
,摘除C(一主一从除外)
- 根据新的角色域名重置监控(修改Consul Node名称并重启)
- 拓扑调整
- 重定向其他从库,将其
primary_conninfo
指向C,作为级连从库,滚动重启生效,并追赶新主库C。
- 如果使用一主一从,之前C仍然承接读流量,则拓扑调整完成后将C摘除。
- 修复旧主库P(如果是一主一从配置且读写负载单台C撑不住,则需要立刻进行,否则这一步不紧急)
- 修复有以下两种方式:Rewind,Remake
- Rewind P:(可选)将旧主库Rewind后作为新从库(如果只有一主一从则是必选)
- 运行
pg_rewind
,如果成功则继续,如果失败则直接重做从库。
- 修改
recovery.conf(12-)|postgresql.auto.conf(12)
,将其primary_conninfo
指向C
- 自动生成P的新角色域名:
< max(standby_sequence) + 1>.standby.
- 集群从库域名/VIP解析变更:
standby.
,向S中添加P,承接读流量
- 根据角色域名重置监控
- Remake P:
- 以新角色域名
< max(standby_sequence) + 1>.standby.
向集群添加新从库。
3 - 系统架构
介绍Pigsty的系统架构
Architecture
Pigsty is based on open source projects like prometheus, grafana, pg_exporter
and follow their best practices.
TL;DR
-
Grafana provides the final user interface, turn metrics into charts.
-
Prometheus scrape, collect metrics and serve queries
-
Exporter (node, postgres, pgbouncer, haproxy) expose server metrics
-
Exporter service are registed into consul, and be discovered by prometheus
-
Read more about pg_exporter
-
Available metrics

4 - 层次关系
介绍Pigsty中涉及的层次关系
Hierarchy
There are several different levels for monitoring:

- Overview: Global views about all instances and clusters among current environment.
- Shard: A brunch of clusters that are horizontal split to serve same business
- Cluster: Basic autonomous unit. Have a designated name (such as
pg-test-tt
) that reflect business, and used as namespace. which usually consist of multiple database instances, contains multiple nodes, and two typical serivce: <cluster>-primary
(read-write) and <cluster>-replica
(read-only).
- Service: Service is an abstraction on addressible server
- Instance: A specific database server, could be single process, a brunch of processes, or multiple containers in a pod.
- Database: A database instance/cluster may have one or more database
- Table/Query : In-Database object monitoring
Basic Facts
- Cluster is the minimal autonomous unit
- Cluster contain nodes (1:n)
- Cluster include services (1:2)
- Cluster consist of instances (1:n)
- Service resolve/route to instance (1:n)
- Instances deployed on nodes (1:1 or n:1)
Hierarchy of Dashboards

Hierarchy of Metrics

5 - 监控面板
Pigsty监控面板简介
Dashboards
PG Overview
PG Overview dashboard is the entrance of entire monitoring system.
Indexing clusters and instances, finding anomalies. Visualizing key metrics.
Other overview level dashboards:
- PG Overview: Home, index page
- PG Alerts: Simple alerting system based on grafana
- PG KPI: Key mertrics overview

Overview of entire environment
PG Cluster Dashboard
Index page for database cluster resource: services, instances, nodes.
Aggregated metrics on cluster level.
Cluster level dashboards:
- PG Cluster
- PG Cluster All
- PG Cluster Node
- PG Cluster Replication
- PG Cluster Activity
- PG Cluster Query
- PG Cluster Session
- PG Cluster Persist
- PG Cluster Stat

Dashboard that focus on an autonomous database cluster
PG Service Dashboard
PG Service Dashboard focusing on proxy , servers, traffic routes.

Focusing on DNS, read-write/read-only, traffic routing, proxy & server health, etc…
PG Instsance Dashboard
PG Instance Dashboard provides tons of metrics

Focusing on instance level metrics
PG Database Dashboard
There may be multiple databases sharing same instance / cluster. So metrics here are focusing on one specific database rather than entire instance.

Focusing on database level metrics
PG Table Overview
PG Table Overview dashboard focus on objects within a database. For example: Table, Index, Function.

Focusing on tables of a specific database
PG Query
This dashboard focus on specific query in a specific database. It provides valuable informtion on database loads.

PG Table Catalog
PG Table Catalog will query database catalog directly using monitor user. It is not recommend but sometimes convinient.

View system catalog information of any specific table in database directly
Node

Classical Node Exporter Dashboard

6 - 监控指标
介绍Pigsty中的监控指标
Metrics
There are tons of metrics available in Pigsty.

那么,Pigsty总共包含了多少指标呢? 这里是一副各个指标来源占比的饼图。我们可以看到,右侧蓝绿黄对应的部分是数据库及数据库相关组件所暴露的指标,而左下方红橙色部分则对应着机器节点相关指标。左上方紫色部分则是负载均衡器的相关指标。
数据库指标中,与postgres本身有关的原始指标约230个,与中间件有关的原始指标约50个,基于这些原始指标,Pigsty又通过层次聚合与预计算,精心设计出约350个与DB相关的衍生指标。
因此,对于每个数据库集群来说,单纯针对数据库及其附件的监控指标就有621个。而机器原始指标281个,衍生指标83个一共364个。加上负载均衡器的170个指标,我们总共有接近1200类指标。
注意,这里我们必须辨析一下metric 与 Time-series的区别。
这里我们使用的量词是 类 而不是个 。 因为一个meitric可能对应多个时间序列。例如一个数据库中有20张表,那么 pg_table_index_scan 这样的Mertric就会对应有20个Time Series
Source
Metrics are collected from exporters.
- Node Metrics (around 2000+ per instance)
- Postgres database metrics and pgbouncer connection pooler metrics (1000+ per instance)
- HAProxy load balancer metrics (400+ per instance)
Pigsty的监控数据,主要有四个来源: 数据库本身,中间件,操作系统,负载均衡器。通过相应的exporter对外暴露。
所有的这些指标,还会进行进一步的加工处理。比如,按照不同的层次进行聚合


Category
Metrics can be categorized as four major groups: Error, Saturation, Traffic and Latency.
- Errors
- Config Errors: NUMA, Checksum, THP, Sync Commit, etc…
- Hardware errors: EDAC Mem Error
- Software errors: TCP Listen Overflow, NTP time shift.
- Service Aliveness: node, postgres,pgbouncer,haproxy,exporters, etc…
- Client Queuing, Idle In Transaction, Sage, Deadlock, Replication break, Rollbacks, etc….
- Saturation
- PG Load, Node Load
- CPU Usage, Mem Usage, Disk Space Usage, Disk I/O Usage, Connection Usage, XID Usage
- Cache Hit Rate / Buffer Hit Rate
- Traffic
- QPS, TPS, Xacts, Rollbacks, Seasonality
- In/Out Bytes of NIC/Pgbouncer, WAL Rate, Tuple CRUD Rate, Block/Buffer Access
- Disk I/O, Network I/O, Mem Swap I/O
- Latency
- Transaction Response Time (Xact RT)
- Query Response Time (Query RT)
- Statement Response Time (Statement RT)
- Disk Read/Write Latency
- Replication Lag (in bytes or seconds)
There are just a small portion of metrics.
Derived Metrics
In addition to metrics above, there are a large number of derived metrics. For example, QPS from pgbouncer will have following derived metrics

################################################################
# QPS (Pgbouncer) #
################################################################
# TPS realtime (irate1m)
- record: pg:db:qps_realtime
expr: irate(pgbouncer_stat_total_query_count{}[1m])
- record: pg:ins:qps_realtime
expr: sum without(datname) (pg:db:qps_realtime{})
- record: pg:svc:qps_realtime
expr: sum by(cls, role) (pg:ins:qps_realtime{})
- record: pg:cls:qps_realtime
expr: sum by(cls) (pg:ins:qps_realtime{})
- record: pg:all:qps_realtime
expr: sum(pg:cls:qps_realtime{})
# qps (rate1m)
- record: pg:db:qps
expr: pgbouncer_stat_avg_query_count{datname!="pgbouncer"}
- record: pg:ins:qps
expr: sum without(datname) (pg:db:qps)
- record: pg:svc:qps
expr: sum by (cls, role) (pg:ins:qps)
- record: pg:cls:qps
expr: sum by(cls) (pg:ins:qps)
- record: pg:all:qps
expr: sum(pg:cls:qps)
# qps avg30m
- record: pg:db:qps_avg30m
expr: avg_over_time(pg:db:qps[30m])
- record: pg:ins:qps_avg30m
expr: avg_over_time(pg:ins:qps[30m])
- record: pg:svc:qps_avg30m
expr: avg_over_time(pg:svc:qps[30m])
- record: pg:cls:qps_avg30m
expr: avg_over_time(pg:cls:qps[30m])
- record: pg:all:qps_avg30m
expr: avg_over_time(pg:all:qps[30m])
# qps µ
- record: pg:db:qps_mu
expr: avg_over_time(pg:db:qps_avg30m[30m])
- record: pg:ins:qps_mu
expr: avg_over_time(pg:ins:qps_avg30m[30m])
- record: pg:svc:qps_mu
expr: avg_over_time(pg:svc:qps_avg30m[30m])
- record: pg:cls:qps_mu
expr: avg_over_time(pg:cls:qps_avg30m[30m])
- record: pg:all:qps_mu
expr: avg_over_time(pg:all:qps_avg30m[30m])
# qps σ: stddev30m qps
- record: pg:db:qps_sigma
expr: stddev_over_time(pg:db:qps[30m])
- record: pg:ins:qps_sigma
expr: stddev_over_time(pg:ins:qps[30m])
- record: pg:svc:qps_sigma
expr: stddev_over_time(pg:svc:qps[30m])
- record: pg:cls:qps_sigma
expr: stddev_over_time(pg:cls:qps[30m])
- record: pg:all:qps_sigma
expr: stddev_over_time(pg:all:qps[30m])
There are hundreds of rules defining extra metrics based on primitive metrics.