高可用原理

Patroni、Etcd、HAProxy 如何协同工作,实现 PostgreSQL 集群的故障自愈。

Pigsty 的高可用架构基于三个核心组件的协同工作:Patroni 负责管理 PostgreSQL 进程与故障切换,Etcd 提供分布式共识与领导者选举,HAProxy 负责流量路由与健康检查。


架构概览

                          ┌─────────────────────────────────────────────────────────┐
                          │                        Etcd 集群                         │
                          │   ┌─────────┐    ┌─────────┐    ┌─────────┐            │
                          │   │  etcd1  │◄──►│  etcd2  │◄──►│  etcd3  │            │
                          │   └────▲────┘    └────▲────┘    └────▲────┘            │
                          └────────┼──────────────┼──────────────┼─────────────────┘
                                   │              │              │
              ┌────────────────────┼──────────────┼──────────────┼────────────────────┐
              │                    │              │              │                    │
              │              ┌─────┴─────┐  ┌─────┴─────┐  ┌─────┴─────┐             │
              │              │  Patroni  │  │  Patroni  │  │  Patroni  │             │
              │              └─────┬─────┘  └─────┬─────┘  └─────┬─────┘             │
              │                    │              │              │                    │
              │              ┌─────┴─────┐  ┌─────┴─────┐  ┌─────┴─────┐             │
              │              │PostgreSQL │  │PostgreSQL │  │PostgreSQL │             │
              │              │  Primary  │  │  Replica  │  │  Replica  │             │
              │              └─────┬─────┘  └─────┬─────┘  └─────┬─────┘             │
              │                    │              │              │                    │
              │                    └──────────────┼──────────────┘                    │
              │                                   │                                   │
              │                          流式复制 (WAL)                               │
              │                                                                       │
              │         ┌─────────────────────────────────────────────────┐          │
              │         │                   HAProxy                        │          │
              │         │  ┌──────────┐  ┌──────────┐  ┌──────────┐       │          │
              │         │  │Port 5433 │  │Port 5434 │  │Port 5436 │  ...  │          │
              │         │  │ Primary  │  │ Replica  │  │ Default  │       │          │
              │         │  └──────────┘  └──────────┘  └──────────┘       │          │
              │         └─────────────────────────────────────────────────┘          │
              │                                                                       │
              └───────────────────────────────────────────────────────────────────────┘
                                               PostgreSQL 集群

组件职责

PostgreSQL

PostgreSQL 是整个系统的核心,提供关系型数据库服务。

  • 使用标准流复制(Streaming Replication)搭建物理从库
  • 主库接受读写请求,从库接受只读请求
  • 在多个节点上部署相同集群名的实例,自动形成主从复制拓扑

Patroni

Patroni 是高可用的控制平面,负责管理 PostgreSQL 进程的完整生命周期。

  • 将 PostgreSQL 作为子进程启动和管理
  • 监控 PostgreSQL 的健康状态
  • 与 Etcd 交互进行领导者选举和配置存储
  • 提供 REST API(默认端口 8008)供健康检查使用
  • 执行自动故障转移(Failover)和主动切换(Switchover)

Etcd

Etcd 是分布式配置存储(DCS),为高可用提供共识基础。

  • 存储集群的元数据和配置信息
  • 提供分布式锁机制实现领导者选举
  • 集群领导者持有租约,心跳续期
  • 当领导者失联超时,触发新一轮选举

HAProxy

HAProxy 是流量入口,负责服务路由和负载均衡。

  • 通过 Patroni REST API 进行健康检查
  • 根据实例角色(Primary/Replica)分发流量
  • 不同端口对应不同服务:5433(读写)、5434(只读)、5436(直连)
  • 故障切换对应用透明,无需修改连接串

工作流程

正常运行时

  1. Patroni 定期向 Etcd 发送心跳,续期领导者租约
  2. Patroni 监控本地 PostgreSQL 健康状态
  3. Patroni 通过 REST API 对外暴露实例角色
  4. HAProxy 周期性检查 Patroni API,维护后端池
  5. 客户端流量通过 HAProxy 路由到正确的实例

从库故障时

  1. HAProxy 检测到从库 Patroni API 不可达
  2. HAProxy 将该从库从后端池中移除
  3. 只读流量自动路由到其他健康从库
  4. 如果所有从库都故障,只读流量回退到主库
  5. 影响:部分只读查询闪断,立即恢复

主库故障时

  1. 主库 Patroni 停止向 Etcd 发送心跳
  2. Etcd 租约过期(默认 10 秒),释放领导者锁
  3. 存活的从库 Patroni 竞争领导者锁
  4. 数据最完整的从库(LSN 最高)胜出
  5. 胜选从库提升为新主库,其他从库重新指向新主库
  6. HAProxy 检测到角色变化,更新路由
  7. 影响:写服务短暂不可用(15s ~ 30s)

关键参数

参数 默认值 说明
pg_rto 30 恢复时间目标(秒),用于计算 Patroni TTL
pg_rpo 1048576 恢复点目标(字节),控制允许的数据丢失量
patroni_watchdog_mode off 看门狗模式,可启用硬件隔离防止脑裂
pg_conf oltp.yml 配置模板,crit.yml 启用同步复制

同步复制

默认配置使用异步复制,主库故障时可能丢失少量未复制的数据(通常 < 1MB)。

如果需要确保零数据丢失(RPO = 0),可以启用同步复制:

pg_conf: crit.yml          # 使用关键业务模板
pg_rpo: 0                   # 恢复点目标设为零

crit.yml 模板自动启用:

  • synchronous_mode: true:启用同步复制
  • synchronous_commit: on:事务提交需等待从库确认
  • 至少一个同步从库确认后事务才算提交成功

代价:写入延迟增加,吞吐量下降,从库故障会影响主库写入。