Loading... # Patroni + HAProxy + Keepalived + watchdog + ETCD PostgreSQL 高可用集群架构分析 # 一、背景与目标 ## 1. 项目背景 ### A. 业务场景 PostgreSQL 作为主流开源关系型数据库,在企业核心业务系统中扮演着关键角色。传统单节点部署存在单点故障风险,主从复制方案在主节点故障时需要手动切换,影响业务连续性。 ### B. 痛点分析 - 单点故障:主节点宕机导致服务中断 - 手动切换:故障恢复需要人工介入,耗时长 - 脑裂风险:网络分区可能导致多主节点 - 数据一致性问题:主备切换时数据可能丢失 ## 2. 设计目标 ### A. 功能目标 - 实现自动故障检测与切换 - 保障数据一致性和完整性 - 提供读写分离能力 ### B. 非功能目标 - 高可用性:99.99% 以上 - 故障切换时间:毫秒级 - 业务无感知:透明切换 - 防止脑裂:分布式共识保障 # 二、总体架构 ## 1. 设计原则 - 分层架构:客户端应用层、负载均衡层、数据库集群层、分布式一致性层 - 自动化运维:故障自动检测、自动切换、自动恢复 - 防止脑裂:基于分布式共识的选举机制 - 读写分离:智能路由优化性能 ## 2. 系统架构 ```mermaid graph TB Client[客户端应用层] --> VIP[虚拟 IP 192.168.231.140] VIP -->|VRRP 协议| Keep1[Keepalived Master] VIP -->|VRRP 协议| Keep2[Keepalived Backup] Keep1 --> HA1[HAProxy 主节点] Keep2 --> HA2[HAProxy 备节点] HA1 -->|读写分离| Patroni1[Patroni Leader] HA1 -->|只读| Patroni2[Patroni Follower] HA1 -->|只读| Patroni3[Patroni Follower] HA2 --> Patroni1 HA2 --> Patroni2 HA2 --> Patroni3 Patroni1 --> PG1[(PostgreSQL 主节点)] Patroni2 --> PG2[(PostgreSQL 备节点)] Patroni3 --> PG3[(PostgreSQL 备节点)] Patroni1 -.分布式共识.-> ETCD1[(ETCD 节点 1)] Patroni2 -.分布式共识.-> ETCD2[(ETCD 节点 2)] Patroni3 -.分布式共识.-> ETCD3[(ETCD 节点 3)] WD1[Watchdog 监控] -.心跳检测.-> Patroni1 WD2[Watchdog 监控] -.心跳检测.-> Patroni2 WD3[Watchdog 监控] -.心跳检测.-> Patroni3 ```   ## 3. 组件说明 - **客户端应用层**:业务系统通过统一 VIP 访问,对底层架构无感知 - **负载均衡层**:HAProxy + Keepalived 实现智能路由和负载均衡层高可用 - **数据库集群层**:PostgreSQL + Patroni 实现数据高可用和自动故障转移 - **分布式一致性层**:ETCD 集群提供强一致性保障,防止脑裂 - **进程监控层**:Watchdog 监控 Patroni 进程状态,异常时强制重启 # 三、负载均衡层设计 ## 1. HAProxy 组件 ### A. 组件职责 HAProxy(High Availability Proxy)是开源高性能代理软件,在架构中负责: - 接收客户端连接请求 - 根据 PostgreSQL 节点角色进行读写分离路由 - 执行健康检查,自动剔除故障节点 - 实现负载均衡,优化资源利用 ### B. 核心架构 ```mermaid graph LR Client[客户端请求] --> Frontend[Frontend 前端处理] Frontend --> LB[Load Balancer 负载均衡] LB --> Backend[Backend 后端管理] Backend --> HC[Health Checker 健康检查] Backend --> CM[Connection Manager 连接管理] Backend --> Server1[(PostgreSQL 主节点)] Backend --> Server2[(PostgreSQL 备节点 1)] Backend --> Server3[(PostgreSQL 备节点 2)] HC -->|健康检查| Server1 HC -->|健康检查| Server2 HC -->|健康检查| Server3 CM --> SE[Statistics Engine 统计引擎] ```   ### C. 请求处理流程 ```mermaid sequenceDiagram participant C as 客户端 participant H as HAProxy participant P as Patroni/PostgreSQL C->>H: 1. 发起连接 H->>H: 2. Accept Connection H->>H: 3. Parse Request H->>H: 4. Route Request H->>H: 5. Select Server(读写分离) H->>P: 6. Connect to Server P-->>H: 7. Connection Established C->>H: 8. Proxy Traffic H->>P: 9. Forward Request P-->>H: 10. Response H-->>C: 11. Process Response H->>C: 12. Close Connection ```   ### D. 健康检查配置 ```bash default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions inter 3s # 健康检查间隔 3 秒 fall 3 # 连续 3 次失败标记为 down rise 2 # 连续 2 次成功标记为 up option pgsql-check # PostgreSQL 专用健康检查 timeout connect 5s # 连接超时 5 秒 timeout server 30s # 服务器响应超时 30 秒 ```  ### E. 负载均衡算法 - **Round Robin**:轮询算法,默认方式 - **Least Connections**:最少连接算法 - **Source IP Hashing**:源 IP 哈希算法 - **URI Hashing**:URI 哈希算法 ### F. 健康检查类型 - **TCP Check**:TCP 端口连通性检查 - **HTTP Check**:HTTP 请求和响应检查 - **SSL Check**:SSL 证书和连接检查 - **PostgreSQL Check**:PostgreSQL 数据库检查 ## 2. Keepalived 组件 ### A. 组件职责 Keepalived 通过 VRRP 协议实现虚拟 IP 高可用,为 HAProxy 主备节点提供心跳检测与故障切换,确保负载均衡层无单点故障。 ### B. 核心架构 ```mermaid graph TB VRRP[VRRP 模块] -->|心跳广播| Master[主节点 Priority 100] VRRP -->|心跳广播| Backup[备节点 Priority 90] Master -->|持有 VIP| VIP[虚拟 IP 192.168.231.140] Backup -->|待机| VIP HC[健康检查模块] -->|监控 HAProxy| Master HC -->|监控 HAProxy| Backup HC -->|优先级调整| VRRP SE[脚本执行器] -->|chk_haproxy.sh| HC NS[通知系统] -->|状态变化告警| VRRP IPVS[IPVS 集成] -->|负载均衡| VRRP ```   ### C. VRRP 状态转换 ```mermaid stateDiagram-v2 [*] --> INIT: 系统启动 INIT --> BACKUP: 初始化完成 BACKUP --> MASTER: 收到更高优先级广告<br/>或选举超时 MASTER --> BACKUP: 收到更高优先级广告 MASTER --> FAULT: 健康检查失败 BACKUP --> FAULT: 健康检查失败 FAULT --> BACKUP: 故障恢复 ```   ### D. 配置示例 ```bash vrrp_instance VI_1 { state MASTER # 主节点 MASTER,备节点 BACKUP interface eth0 # 网络接口 virtual_router_id 51 # 虚拟路由 ID priority 100 # 主节点优先级 100,备节点 90 advert_int 1 # VRRP 心跳广播间隔 1 秒 authentication { auth_type PASS auth_pass 62f7f8e5 } virtual_ipaddress { 192.168.231.140/24 # 虚拟 IP 地址 } } vrrp_script chk_haproxy { script "/check/haproxy.sh" interval 3 # 检查间隔 3 秒 timeout 2 # 超时时间 2 秒 rise 2 # 成功阈值 2 次 fall 3 # 失败阈值 3 次 weight -30 # 优先级调整权重 } ``` ### E. 故障处理机制 - **主节点故障**:自动选举新主节点,VIP 无缝转移 - **健康检查失败**:优先级自动调整,触发状态切换 - **服务恢复**:自动回到正常状态,重新参与选举 # 四、分布式一致性层设计 ## 1. ETCD 组件 ### A. 组件职责 ETCD 是基于 Raft 协议的分布式键值存储,为 Patroni 集群提供强一致性的状态存储与共识服务: - 记录数据库节点角色信息 - 存储 Leader 选举信息 - 维护集群配置数据 - 保障 Leader 选举唯一性,防止脑裂 ### B. 核心架构 ```mermaid graph TB Client[Patroni 客户端] --> API[API Server] API --> Raft[Raft 一致性模块] Raft --> Log[日志存储] Raft --> Snapshot[快照存储] Raft --> WAL[WAL 预写日志] Log --> Store[(键值存储)] Snapshot --> Store WAL --> Store Raft -->|心跳广播| Node1[ETCD 节点 1] Raft -->|心跳广播| Node2[ETCD 节点 2] Raft -->|心跳广播| Node3[ETCD 节点 3] ```   ### C. Raft 选举流程 ```mermaid sequenceDiagram participant F1 as Follower 节点 1 participant F2 as Follower 节点 2 participant F3 as Follower 节点 3 participant L as Leader Note over F1,F3: Step 1: Follower State<br/>等待 Leader 心跳 F3->>F3: Election Timeout 超时 Note over F1,F3: Step 2: Election Timeout<br/>触发选举 F3->>F3: 转换为 Candidate State Note over F1,F3: Step 3: Candidate State<br/>增加任期,发起投票 F3->>F1: RequestVote (任期 N) F3->>F2: RequestVote (任期 N) Note over F1,F3: Step 4: Vote Collection<br/>收集投票 F1-->>F3: 投票同意 F2-->>F3: 投票同意 Note over F1,F3: Step 5: Leader Election<br/>获得多数票成为 Leader F3->>F3: 成为 Leader Note over F1,F3: Step 6: Leader State<br/>发送心跳维持权威 F3->>F1: AppendEntries 心跳 F3->>F2: AppendEntries 心跳 ```   ### D. 选举参数配置 ```bash --heartbeat-interval=100ms # Leader 心跳间隔 --election-timeout=1000ms # 选举超时时间 --min-election-timeout=1000ms # 最小选举超时 --max-election-timeout=2000ms # 最大选举超时 --initial-election-tick-advance=true # 初始选举优化 ``` # 五、进程监控层设计 ## 1. Watchdog 组件 ### A. 组件职责 Watchdog 通过接收 Patroni 的定时心跳来监控其运行状态: - 监控 Patroni 进程健康状态 - 检测进程假死或心跳超时 - 触发服务或系统重启 - 防止故障节点导致脑裂 ### B. 核心架构 ```mermaid graph TB Patroni[Patroni 进程] -->|每 10 秒心跳| WD[Watchdog 监控器] WD -->|心跳超时 30 秒| Systemd[Systemd 服务管理器] Systemd -->|重启服务| Patroni WD -->|最后手段| Kernel[Linux Kernel Watchdog] Kernel -->|强制重启| System ```   ### C. 配置示例 ```yaml # Watchdog 配置 watchdog: mode: automatic safety_margin: 5 # 安全裕度 5 秒 interval: 10 # 心跳间隔 10 秒 timeout: 30 # 超时时间 30 秒 # Systemd 服务配置 [Service] WatchdogSec=30s # 看门狗超时 30 秒 Restart=on-failure # 失败时重启 RestartSec=1s # 重启间隔 1 秒 StartLimitBurst=3 # 启动限制次数 StartLimitInterval=60s # 启动限制时间窗口 ``` ### D. 故障场景处理 - **脑裂问题**:多个主节点同时存在 - **进程假死**:Patroni 进程存在但无响应 - **网络分区**:节点与 ETCD 集群隔离 - **资源耗尽**:CPU、内存或磁盘资源不足 ### E. 恢复处理流程 ```mermaid graph TB Start[故障检测] --> Check{心跳超时?} Check -->|是| Alert[告警通知] Check -->|否| Monitor[继续监控] Alert --> Restart[服务重启] Restart --> Success{恢复成功?} Success -->|是| Verify[恢复验证] Success -->|否| SystemReboot[系统重启] SystemReboot --> Verify Verify --> End[恢复完成] Monitor --> Start ```   ### F. 防止脑裂机制 - **心跳超时检测**:30 秒内未收到心跳触发告警 - **自动重启机制**:防止故障节点继续写入数据 - **集群状态验证**:与 ETCD 集群状态对比 - **数据一致性检查**:验证 WAL 日志位置 # 六、数据库集群层设计 ## 1. Patroni 组件 ### A. 组件职责 Patroni 是 PostgreSQL 高可用架构的核心管家: - 实现自动化的主备选举 - 执行故障检测与故障转移 - 实时监控数据库状态 - 维护集群配置一致性 - 协调主备节点的流复制同步 - 对接 HAProxy 实现流量智能路由 ### B. 核心架构 ```mermaid graph TB EM[Election Manager 选举管理器] -->|状态转换| HM[Health Monitor 健康监控器] HM -->|节点状态检测| PG[PostgreSQL 数据库] EM -->|分布式共识| EC[ETCD Client] EC -->|存储/读取状态| ETCD[(ETCD 集群)] PG -->|角色信息| HM HM -->|健康检查| EM EM -->|REST API| API[REST API 接口] API -->|状态查询| Monitor[监控系统] API -->|手动干预| Admin[管理员] ```   ### C. 选举状态流程 ```mermaid stateDiagram-v2 [*] --> INIT: 系统初始化 INIT --> FOLLOWER: 加入集群 FOLLOWER --> CANDIDATE: Leader 故障检测 CANDIDATE --> LEADER: 获得多数票 CANDIDATE --> FOLLOWER: 未获得多数票 LEADER --> DEMOTED: 主动降级或故障 DEMOTED --> FOLLOWER: 降级完成 LEADER --> FOLLOWER: 重新选举 ```   ### D. 选举流程详解 ```mermaid sequenceDiagram participant F1 as Follower 节点 1 participant F2 as Follower 节点 2 participant F3 as Follower 节点 3 participant E as ETCD 集群 participant PG as PostgreSQL Note over F1,F3: 故障检测 F1->>E: 检测 Leader 心跳超时 F2->>E: 检测 Leader 心跳超时 Note over F1,F3: 触发选举 F1->>F1: 转换为 CANDIDATE F1->>E: 请求投票 F2->>E: 投票给 F1 Note over F1,F3: 收集选票 E-->>F1: 获得多数票 F1->>F1: 成为 Leader Note over F1,F3: 提升 PostgreSQL F1->>PG: 提升为主节点 PG-->>F1: 提升成功 Note over F1,F3: 通知集群 F1->>E: 更新集群状态 E-->>F2: 新 Leader 通知 E-->>F3: 新 Leader 通知 ```   ### E. 配置示例 ```yaml dcs: ttl: 30 # Leader 租约超时时间 30 秒 loop_wait: 10 # 心跳发送间隔 10 秒 retry_timeout: 10 # 重试超时时间 10 秒 maximum_lag_on_failover: 1048576 # 最大复制延迟 1MB election: retry_timeout: 10 # 选举重试超时 10 秒 maximum_retry_timeout: 30 # 最大选举重试超时 30 秒 retry_interval: 2 # 选举重试间隔 2 秒 priority: 100 # 节点优先级 ``` ### F. 防止脑裂机制 - **ETCD 共识保障**:使用分布式锁和租约机制 - **多数票原则**:必须获得集群多数节点的支持 - **自动降级机制**:故障节点自动降级避免数据不一致 # 七、技术选型 ## 1. 技术栈对比 | 组件层次 | 技术选型 | 替代方案 | 选择理由 | |---------|---------|---------|---------| | 负载均衡 | HAProxy | Nginx、LVS | 性能优秀、PostgreSQL 专用健康检查 | | VIP 高可用 | Keepalived | Heartbeat | 轻量级、配置简单、VRRP 标准 | | 分布式共识 | ETCD | Consul、ZooKeeper | Raft 协议、强一致性、Go 语言高性能 | | 数据库高可用 | Patroni | RePM、Pgpool | Python 开发、社区活跃、功能完善 | | 进程监控 | Watchdog | Monit | 系统级保障、硬件级重启能力 | ## 2. 性能指标 - 故障检测时间:10-30 秒 - 故障切换时间:毫秒级 - 数据零丢失:基于同步复制 - 支持 5 万+ QPS # 八、高可用机制分析 ## 1. 多层级高可用保障 ```mermaid graph TB subgraph 第一层 VIP[虚拟 IP] --> Keep[Keepalived 主备] end subgraph 第二层 Keep --> HA[HAProxy 负载均衡] end subgraph 第三层 HA --> Pat[Patroni 集群] end subgraph 第四层 Pat --> PG[PostgreSQL 主备] end subgraph 第五层 Pat --> ETCD[ETCD 共识] WD[Watchdog] -.监控.-> Pat end ```   ## 2. 故障场景处理 | 故障类型 | 检测方式 | 恢复机制 | 恢复时间 | |---------|---------|---------|---------| | HAProxy 主节点故障 | Keepalived 健康检查 | VIP 切换至备节点 | 3-5 秒 | | PostgreSQL Leader 故障 | Patroni 健康监控 | 自动选举新 Leader | 20-30 秒 | | Patroni 进程假死 | Watchdog 心跳检测 | 强制重启服务/系统 | 30-60 秒 | | ETCD 节点故障 | Raft 协议 | 自动选举新 ETCD Leader | 1-2 秒 | | 网络分区 | 多数票原则 | 隔离少数派节点 | 选举超时 | # 九、监控告警 ## 1. 监控指标 - **HAProxy 层**:连接数、队列长度、响应时间、后端节点状态 - **Keepalived 层**:VIP 状态、VRRP 状态、节点优先级 - **Patroni 层**:节点角色、复制延迟、选举状态 - **PostgreSQL 层**:连接数、TPS、锁等待、WAL 位置 - **ETCD 层**:集群健康、Leader 状态、提案延迟 - **Watchdog 层**:心跳状态、重启次数 ## 2. 告警规则 - VIP 切换告警 - PostgreSQL 主备切换告警 - 复制延迟超阈值告警 - ETCD 集群成员变更告警 - Watchdog 触发重启告警 # 十、参考资料 1. [Patroni + HAProxy + Keepalived + ETCD 搭建高可用 PostgreSQL 集群](https://mp.weixin.qq.com/s/G4J9xH9XaW0Be76XLEW5Qw) 最后修改:2026 年 01 月 15 日 © 允许规范转载 赞 如果觉得我的文章对你有用,请随意赞赏