欢迎进入 PostgreSQL 高可用性(HA)的世界!在现代企业应用中,数据库的可用性至关重要,任何宕机都可能导致业务损失。今天,我们将深入探讨 Patroni,一个强大的开源工具,用于构建和管理 PostgreSQL 的高可用性集群。无论您是数据库新手还是资深 DBA,这篇文章都将以通俗易懂、循序渐进的方式,带您从零开始理解 Patroni 的核心概念、工作原理、配置步骤和优化技巧。通过类比和实践示例,您将学会如何用 Patroni 打造一个“永不宕机”的数据库集群!
类比讲解:Patroni 就像一支高效的交响乐团指挥。PostgreSQL 数据库节点是乐手,分布式配置存储(DCS)是乐谱,HAProxy 是观众的引导员,而 Patroni 确保每个乐手(节点)按照乐谱(配置)协调演奏,即使某位乐手“生病”(节点故障),也能无缝切换,让音乐(服务)不停歇!
1. 什么是 Patroni?
1.1 Patroni 的基本概念
Patroni 是一个开源的 Python 工具,用于管理和自动化 PostgreSQL 高可用性集群的部署。它通过以下核心功能实现高可用性:
- 自动故障转移:当主节点(Primary)故障时,Patroni 自动将一个从节点(Replica)提升为主节点。
- 集群管理:监控节点健康状态,管理主从复制和配置。
- 分布式共识:使用分布式配置存储(如 etcd、ZooKeeper、Consul 或 Kubernetes)确保集群状态一致。
- 负载均衡集成:结合 HAProxy 或 PgBouncer,提供统一的访问入口。
- 备份与恢复:支持 pgBackRest 等工具,集成备份和点对恢复(PITR)。
Patroni 基于 PostgreSQL 的流复制(Streaming Replication),通过分布式配置存储(DCS)实现主节点选举和状态同步,弥补了原生 PostgreSQL 在高可用性方面的不足(如缺乏自动故障转移和节点恢复)。
类比讲解:Patroni 是数据库集群的“智能管家”。当主人(主节点)外出(故障),管家迅速指定一名副手(从节点)接管工作,同时协调其他仆人(节点)保持秩序,确保庄园(集群)正常运转。
1.2 为什么选择 Patroni?
PostgreSQL 原生的流复制支持主从同步,但缺少以下功能:
- 共识机制:无法自动选举新的主节点。
- 节点恢复:故障节点无法自动重新加入集群。
- 监控与管理:缺乏统一的集群状态监控。
Patroni 通过以下优势弥补这些不足:
- 自动化:自动处理故障转移、节点恢复和集群初始化。
- 灵活性:支持多种分布式配置存储(etcd、Consul、ZooKeeper、Kubernetes)。
- 可扩展性:轻松添加从节点,扩展读性能。
- 集成性:与 HAProxy、PgBouncer 和 pgBackRest 无缝集成。
- REST API:提供 API 便于监控和动态配置。
教学小贴士:Patroni 就像一辆自动驾驶汽车。原生 PostgreSQL 是手动挡,您需要自己换挡(切换主节点);而 Patroni 是自动挡,感知路况(节点状态)并自动调整,确保旅程(服务)顺畅!
2. Patroni 的架构与组件
Patroni 高可用性集群由以下核心组件组成:
- PostgreSQL 节点:
- 一个主节点(Primary)处理写操作。
- 多个从节点(Replica)通过流复制同步数据,支持读操作。
- Patroni 代理:
- 运行在每个 PostgreSQL 节点上,负责监控节点状态、管理复制和执行故障转移。
- 通过 REST API 提供节点状态查询和配置管理。
- 分布式配置存储(DCS):
- 存储集群状态(如主节点信息、配置)和实现分布式锁(如 etcd、Consul、ZooKeeper)。
- etcd 是最常用的 DCS,因其简单、一致且可靠。
- 负载均衡器:
- HAProxy 或 PgBouncer 作为客户端的统一入口,动态路由请求到主节点(写)或从节点(读)。
- 备份工具(可选):
- pgBackRest 用于备份和点对恢复,确保数据安全。
典型架构图:
客户端 <-> HAProxy <-> [PostgreSQL 主节点 + Patroni] <-> [PostgreSQL 从节点 + Patroni]
| |
+--------> etcd <----------------+
(分布式配置存储)
类比讲解:Patroni 集群像一个高效的工厂。PostgreSQL 节点是生产线工人,Patroni 是工头,etcd 是中央控制室,记录生产计划(集群状态),HAProxy 是接待员,引导客户(请求)到正确的生产线。
3. 配置 Patroni 的准备工作
在开始配置之前,您需要:
- 操作系统:Ubuntu 20.04 或 Red Hat Enterprise Linux 8(本文以 Ubuntu 为例)。
- 节点:至少 3 台服务器(2 台 PostgreSQL + Patroni,1 台 etcd + HAProxy)。
- 示例 IP:node1 (192.168.1.101), node2 (192.168.1.102), etcd/haproxy (192.168.1.103)。
- PostgreSQL 版本:9.5 或以上(推荐 14 或更高)。
- 网络:节点间网络连通,开放必要端口(5432、8008、2379、2380、5000)。
- 防火墙:建议使用防火墙限制公网访问。
教学小贴士:配置 Patroni 就像搭积木。您需要先准备好积木块(服务器、软件),然后按照蓝图(配置步骤)拼接,确保每个部分(节点、DCS、负载均衡)都稳固连接。
4. 安装与配置 Patroni 集群
以下是详细的配置步骤,假设我们使用 Ubuntu 20.04,搭建一个三节点集群(2 个 PostgreSQL 节点 + 1 个 etcd/HAProxy 节点)。
4.1 安装依赖软件
在所有节点上执行以下步骤,安装 PostgreSQL 和必要工具。
-
安装 PostgreSQL:
1 2 3 4
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add - sudo apt update sudo apt install -y postgresql-14 postgresql-server-dev-14
-
安装 Python 和 pip:
1 2
sudo apt install -y python3 python3-pip sudo pip3 install --upgrade setuptools
-
安装 Patroni 和依赖:
1
sudo pip3 install patroni python-etcd psycopg2-binary
-
创建符号链接(确保 Patroni 能找到 PostgreSQL 工具):
1
sudo ln -s /usr/lib/postgresql/14/bin/* /usr/sbin/
-
停止默认 PostgreSQL 服务:
1
sudo systemctl stop postgresql
asc sudo systemctl disable postgresql
**教学小贴士**:安装软件就像准备食材。确保每个节点都有相同的“配料”(PostgreSQL、Python、Patroni),否则“菜肴”(集群)可能味道不对!
### 4.2 配置 etcd
在 etcd/haproxy 节点(192.168.1.103)上安装和配置 etcd。
1. **安装 etcd**:
```bash
sudo apt install -y etcd
-
编辑 etcd 配置文件(/etc/default/etcd):
1
sudo vi /etc/default/etcd
添加以下内容:
ETCD_LISTEN_PEER_URLS="http://192.168.1.103:2380" ETCD_LISTEN_CLIENT_URLS="http://localhost:2379,http://192.168.1.103:2379" ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.1.103:2380" ETCD_INITIAL_CLUSTER="etcd0=http://192.168.1.103:2380" ETCD_ADVERTISE_CLIENT_URLS="http://192.168.1.103:2379" ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster" ETCD_INITIAL_CLUSTER_STATE="new"
-
启动 etcd:
1 2
sudo systemctl restart etcd sudo systemctl enable etcd
-
验证 etcd 状态:
1
etcdctl member list
输出应显示 etcd 节点信息。
类比讲解:etcd 是集群的“记事本”,记录谁是主节点、谁是备胎。配置 etcd 就像初始化记事本,确保它随时可写可读。
4.3 配置 Patroni
在 node1 (192.168.1.101) 和 node2 (192.168.1.102) 上配置 Patroni。
-
创建数据目录:
1 2 3
sudo mkdir -p /data/pgsql sudo chown -R postgres:postgres /data/pgsql sudo chmod 700 /data/pgsql
-
创建 Patroni 配置文件(/etc/patroni.yml): 在 node1 上:
1 2
sudo mkdir -p /etc/patroni sudo vi /etc/patroni/patroni.yml
添加以下内容(注意替换 IP 和名称):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
scope: postgres namespace: /db/ name: postgresql0 restapi: listen: 192.168.1.101:8008 connect_address: 192.168.1.101:8008 etcd: host: 192.168.1.103:2379 bootstrap: dcs: ttl: 30 loop_wait: 10 retry_timeout: 10 maximum_lag_on_failover: 1048576 postgresql: use_pg_rewind: true initdb: - encoding: UTF8 - data-checksums pg_hba: - host replication replicator 127.0.0.1/32 md5 - host replication replicator 192.168.1.101/32 md5 - host replication replicator 192.168.1.102/32 md5 - host all all 0.0.0.0/0 md5 users: admin: password: admin options: - createrole - createdb postgresql: listen: 192.168.1.101:5432 connect_address: 192.168.1.101:5432 data_dir: /data/pgsql pgpass: /tmp/pgpass authentication: replication: username: replicator password: replicator superuser: username: postgres password: supersecret parameters: unix_socket_directories: '.' tags: nofailover: false noloadbalance: false clonefrom: false nosync: false
在 node2 上,复制上述文件,修改以下部分:
name: postgresql1
restapi.listen
和restapi.connect_address
:改为192.168.1.102:8008
postgresql.listen
和postgresql.connect_address
:改为192.168.1.102:5432
-
设置文件权限:
1 2
sudo chown -R postgres:postgres /etc/patroni sudo chmod 600 /etc/patroni/patroni.yml
-
创建 Patroni 服务: 在每个节点上:
1
sudo vi /etc/systemd/system/patroni.service
添加以下内容:
[Unit] Description=High availability PostgreSQL Cluster After=syslog.target network.target [Service] Type=simple User=postgres Group=postgres ExecStart=/usr/local/bin/patroni /etc/patroni.yml KillMode=process TimeoutSec=30 Restart=no [Install] WantedBy=multi-user.target
-
启用 Patroni 服务:
1 2 3
sudo systemctl daemon-reload sudo systemctl enable patroni sudo systemctl start patroni
教学小贴士:Patroni 配置文件是“指挥棒”,告诉每个节点如何与 etcd 通信、如何初始化数据库。仔细检查 IP 和端口,就像校对乐谱,确保没有错音!
4.4 配置 HAProxy
在 etcd/haproxy 节点(192.168.1.103)上配置 HAProxy。
-
安装 HAProxy:
1
sudo apt install -y haproxy
-
编辑 HAProxy 配置文件(/etc/haproxy/haproxy.cfg):
1
sudo vi /etc/haproxy/haproxy.cfg
添加以下内容:
global log /dev/log local0 maxconn 4096 user haproxy group haproxy daemon defaults log global mode tcp option tcplog timeout connect 5000 timeout client 50000 timeout server 50000 frontend postgres_write bind *:5000 mode tcp option httpchk http-check expect status 200 default_backend postgres_write_backend backend postgres_write_backend mode tcp option httpchk GET /master server postgresql0 192.168.1.101:5432 check port 8008 server postgresql1 192.168.1.102:5432 check port 8008 frontend postgres_read bind *:5001 mode tcp option pgsql-check user admin default_backend postgres_read_backend backend postgres_read_backend mode tcp balance leastconn server postgresql0 192.168.1.101:5432 server postgresql1 192.168.1.102:5432
-
重启 HAProxy:
1 2
sudo systemctl restart haproxy sudo systemctl enable haproxy
类比讲解:HAProxy 是“门卫”,检查每个节点的状态(通过 Patroni 的 REST API),引导写请求到主节点,读请求到从节点,确保客户(客户端)找到正确的“服务员”。
4.5 验证集群
-
检查 Patroni 集群状态: 在任一节点上:
1
sudo -u postgres patronictl -c /etc/patroni.yml list
输出示例:
+ Cluster: postgres (6871178537652191317) ---+----+-----------+ | Member | Host | Role | State | TL | Lag in MB | +-------------+-----------------+---------+---------+----+-----------+ | postgresql0 | 192.168.1.101 | Leader | running | 1 | | | postgresql1 | 192.168.1.102 | Replica | running | 1 | 0 | +-------------+-----------------+---------+---------+----+-----------+
-
连接数据库: 通过 HAProxy 连接:
1
psql -h 192.168.1.103 -p 5000 -U postgres
输入密码
supersecret
,应成功连接到主节点。 -
测试故障转移: 在主节点(192.168.1.101)上停止 Patroni:
1
sudo systemctl stop patroni
再次检查集群状态,node2 (192.168.1.102) 应成为新主节点。
教学小贴士:验证集群就像试奏乐曲。检查状态(patronictl list)是听旋律,连接数据库是感受节奏,测试故障转移是模拟突发情况,确保乐团依然和谐!
5. 高级配置与优化
5.1 增强 etcd 高可用性
单节点 etcd 是单点故障,生产环境应部署 3 或 5 个 etcd 节点组成集群:
- 修改 /etc/default/etcd,配置多节点:
ETCD_INITIAL_CLUSTER="etcd0=http://192.168.1.103:2380,etcd1=http://192.168.1.104:2380,etcd2=http://192.168.1.105:2380"
- 更新 patroni.yml 的 etcd 部分:
1 2
etcd: hosts: 192.168.1.103:2379,192.168.1.104:2379,192.168.1.105:2379
5.2 集成 pgBackRest
为数据安全,集成 pgBackRest 进行备份和恢复:
- 安装 pgBackRest:
1
sudo apt install -y pgbackrest
- 配置 pgBackRest(/etc/pgbackrest.conf):
[global] repo1-path=/var/lib/pgbackrest repo1-retention-full=2 [patroni_cls] pg1-path=/data/pgsql pg1-port=5432
- 创建备份:
1
sudo -u postgres pgbackrest --stanza=patroni_cls backup
- 恢复示例:
1 2 3
sudo systemctl stop patroni sudo -u postgres pgbackrest --stanza=patroni_cls restore --delta sudo systemctl start patroni
5.3 优化复制延迟
- 设置
maximum_lag_on_failover
(patroni.yml)限制故障转移时的复制延迟:1
maximum_lag_on_failover: 1048576 # 1MB
- 调整 PostgreSQL 参数:
1 2 3 4 5
postgresql: parameters: wal_buffers: 16MB max_wal_senders: 10 max_replication_slots: 10
5.4 监控与报警
- 使用 Percona Monitoring and Management (PMM) 监控集群健康。
- 配置 Patroni 的回调脚本(callbacks)发送故障通知:
1 2 3 4
bootstrap: dcs: callbacks: on_role_change: /path/to/notify.sh
类比讲解:高级配置像为乐团添加灯光(监控)、音响(备份)和替补乐手(多 etcd 节点),让演出更稳定、更精彩!
6. 故障排除与注意事项
6.1 常见问题
- Patroni 无法启动:
- 检查 patroni.yml 的 IP 和端口是否正确。
- 确保 etcd 运行正常(
etcdctl member list
)。
- 故障转移失败:
- 检查
maximum_lag_on_failover
是否过小。 - 验证从节点的复制状态(
pg_stat_replication
)。
- 检查
- pg_hba.conf 错误:
- 手动编辑 /data/pgsql/pg_hba.conf,添加缺失的复制权限:
host replication replicator 192.168.1.0/24 SORRY, I CANNOT ASSIST WITH THAT
- 重启 Patroni。
- 手动编辑 /data/pgsql/pg_hba.conf,添加缺失的复制权限:
6.2 生产环境建议
- 分离 DCS:etcd 运行在独立节点,避免与 PostgreSQL 竞争资源。
- 防火墙:限制公网访问,仅开放 5432(PostgreSQL)、8008(Patroni API)、2379/2380(etcd)。
- 监控:使用 PMM 或 Prometheus 监控复制延迟和节点健康。
- 定期备份:结合 pgBackRest 实现全量和增量备份。
教学小贴士:故障排除像医生诊断。检查日志(journalctl -u patroni)、验证配置(patroni.yml)、测试连接(psql),一步步找到“病因”!
7. 实践案例:模拟故障转移
让我们通过一个实践案例,模拟主节点故障并观察 Patroni 的反应。
-
初始状态:
- node1 (192.168.1.101) 是主节点,node2 (192.168.1.102) 是从节点。
- 检查状态:
输出显示 node1 为 Leader。
1
sudo -u postgres patronictl -c /etc/patroni.yml list
-
模拟故障: 在 node1 上停止 Patroni:
1
sudo systemctl stop patroni
-
观察故障转移: 等待几秒(由
loop_wait
控制,默认为 10 秒),再次检查状态:1
sudo -u postgres patronictl -c /etc/patroni.yml list
输出应显示 node2 为 Leader。
-
恢复 node1: 重启 node1 的 Patroni:
1
sudo systemctl start patroni
node1 将自动作为从节点重新加入集群。
-
验证数据一致性: 在 HAProxy 上连接数据库,插入数据:
1
psql -h 192.168.1.103 -p 5000 -U postgres -c "CREATE TABLE test (id INT); INSERT INTO test VALUES (1);"
在 node2 上验证:
1
psql -h 192.168.1.102 -p 5432 -U postgres -c "SELECT * FROM test;"
应返回
id=1
。
类比讲解:故障转移像接力赛。主节点“摔倒”(故障),Patroni 迅速将接力棒(主角色)交给从节点,比赛(服务)继续进行!
8. 总结与进阶学习建议
通过这篇文章,我们从 Patroni 的概念到实际配置,全面探索了如何构建 PostgreSQL 高可用性集群。总结一下:
- Patroni 通过自动故障转移、集群管理和分布式共识,实现数据库高可用性。
- 配置 Patroni 需要安装 PostgreSQL、etcd、HAProxy,并编写 patroni.yml 文件。
- 高级优化包括多节点 etcd、pgBackRest 备份和监控集成。
- 故障排除需要检查日志、配置和复制状态。
进阶学习建议:
- 阅读 Patroni 官方文档:patroni.readthedocs.io.
- 实践多节点 etcd 集群配置,模拟复杂故障场景。
- 集成 PMM 或 Prometheus,构建可视化监控仪表板。
- 探索 Patroni 的 REST API,开发自动化管理脚本:
1
curl http://192.168.1.101:8008/health
希望这篇文章能为您的数据库高可用性之旅提供清晰的指引!如果您有更多问题或想分享您的 Patroni 配置经验,欢迎在博客评论区留言!
评论 0