PostgreSQL 高可用集群部署指南

PostgreSQL 高可用集群部署指南

概述

本指南基于 Patroni + etcd 方案,提供完整的 PostgreSQL 高可用集群部署流程。该方案支持自动故障转移、读写分离、负载均衡等功能,确保数据库的高可用性和可扩展性。

架构组件

  • PostgreSQL 12.17: 核心数据库
  • Patroni: 集群管理和自动故障转移
  • etcd: 分布式键值存储,作为集群状态存储
  • HAProxy: 负载均衡器和读写分离
  • Keepalived: 虚拟IP漂移和高可用

集群规划

本部署使用 3 节点架构:

  • node1: 192.168.95.139
  • node2: 192.168.95.140
  • node3: 192.168.95.141

环境准备

1. 系统要求

  • CentOS 7.x
  • Python 3.6+
  • 3 台物理机或虚拟机
  • 网络互通,防火墙开放必要端口

2. 升级 Python 环境

# 参考 "Centos7设置python3.6 环境"
# 安装 Python 3.6
yum install -y python3 python3-pip

# 设置默认 Python 版本
alternatives --install /usr/bin/python python /usr/bin/python3 60

3. 创建必要目录

# 在所有节点执行
mkdir -p /u1/pgsql/data          # PostgreSQL 数据目录
mkdir -p /etc/patroni/           # Patroni 配置目录
mkdir -p /tmp/patroni02          # Patroni 日志目录

组件安装和配置

1. 安装和配置 etcd 集群

1.1 安装 etcd
# 在所有节点执行
yum install etcd -y
1.2 配置 etcd 集群

节点 1 配置 (/etc/etcd/etcd.conf):

ETCD_DATA_DIR="/var/lib/etcd/codis.etcd"
ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
ETCD_NAME="node1"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.95.139:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.95.139:2379"
ETCD_INITIAL_CLUSTER="node1=http://192.168.95.139:2380,node2=http://192.168.95.140:2380,node3=http://192.168.95.141:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"

节点 2 配置 (/etc/etcd/etcd.conf):

ETCD_DATA_DIR="/var/lib/etcd/codis.etcd"
ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
ETCD_NAME="node2"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.95.140:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.95.140:2379"
ETCD_INITIAL_CLUSTER="node1=http://192.168.95.139:2380,node2=http://192.168.95.140:2380,node3=http://192.168.95.141:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"

节点 3 配置 (/etc/etcd/etcd.conf):

ETCD_DATA_DIR="/var/lib/etcd/codis.etcd"
ETCD_LISTEN_PEER_URLS="http://0.0.0.0:2380"
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
ETCD_NAME="node3"
ETCD_INITIAL_ADVERTISE_PEER_URLS="http://192.168.95.141:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://192.168.95.141:2379"
ETCD_INITIAL_CLUSTER="node1=http://192.168.95.139:2380,node2=http://192.168.95.140:2380,node3=http://192.168.95.141:2380"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
1.3 启动 etcd 服务
# 在所有节点执行
systemctl daemon-reload
systemctl enable etcd
systemctl start etcd

# 验证 etcd 成员列表
etcdctl member list

# 检查集群健康状态
etcdctl --endpoints http://192.168.95.141:2379 cluster-health
1.4 安装 etcd-viewer(可选)
docker pull dontpanic57/etcd-viewer
docker run -d -p 8080:8080 dontpanic57/etcd-viewer

2. 安装 PostgreSQL 12.17

2.1 离线安装 PostgreSQL

下载安装包(注意版本号一致性):

  • postgresql12-libs-12.17-1PGDG.rhel7.x86_64.rpm
  • postgresql12-12.17-1PGDG.rhel7.x86_64.rpm
  • postgresql12-server-12.17-1PGDG.rhel7.x86_64.rpm
  • postgresql12-contrib-12.17-1PGDG.rhel7.x86_64.rpm

按顺序安装

# 在所有节点执行,按依赖顺序安装
rpm -ivh postgresql12-libs-12.17-1PGDG.rhel7.x86_64.rpm
rpm -ivh postgresql12-12.17-1PGDG.rhel7.x86_64.rpm
rpm -ivh postgresql12-server-12.17-1PGDG.rhel7.x86_64.rpm
rpm -ivh postgresql12-contrib-12.17-1PGDG.rhel7.x86_64.rpm

解决依赖问题

# 如遇依赖问题,先在外网下载依赖包
yum install --downloadonly --downloaddir=/pg12_rpm libicu

# 上传至内网服务器后安装
yum install -y libicu-50.2-4.el7_7.x86_64.rpm
2.2 配置 PostgreSQL 数据目录
# 在所有节点执行
chown postgres:postgres /u1/pgsql
chmod -R 700 /u1/pgsql

3. 安装和配置 Patroni

3.1 安装 Patroni
# 安装 Python 依赖
pip install psycopg2-binary -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host=mirrors.aliyun.com
pip3 install patroni[etcd] -i https://mirrors.aliyun.com/pypi/simple/ --trusted-host=mirrors.aliyun.com

# 验证安装
which patroni

常见问题解决

# 如遇 "python setup.py egg_info" 错误
yum remove python-pip
# 到官网重新下载安装 python-pip

# 创建 pip 软链接
ln -sf /usr/local/python3/bin/pip  /usr/bin/pip

# 安装缺失组件
yum install python3-pip python3 python2 python2-pip
3.2 创建 .pgpass 文件
# 在所有节点执行,切换到 postgres 用户
su - postgres
echo "192.168.95.139:5432:postgres:postgres:postgres123" > ~/.pgpass
echo "192.168.95.140:5432:postgres:postgres:postgres123" >> ~/.pgpass
echo "192.168.95.141:5432:postgres:postgres:postgres123" >> ~/.pgpass
chmod 600 ~/.pgpass
exit
3.3 创建 Patroni 配置文件

节点 1 配置 (/etc/patroni/patroni_postgresql.yml):

scope: postgresql12
namespace: /postgresql/
name: node1

# 日志配置
log:
  level: INFO
  traceback_level: ERROR
  dir: /tmp/patroni02
  file_num: 10
  file_size: 104857600

# REST API 配置
restapi:
  listen: 192.168.95.139:8008
  connect_address: 192.168.95.139:8008

# etcd 配置
etcd:
  host: 192.168.95.139:2379
  host: 192.168.95.140:2379
  host: 192.168.95.141:2379

# 集群初始化配置
bootstrap:
  dcs:
    ttl: 30
    loop_wait: 10
    retry_timeout: 10
    maximum_lag_on_failover: 1048576
    master_start_timeout: 300
    synchronous_mode: false
    postgresql:
      use_pg_rewind: true
      use_slots: true
      parameters:
        listen_addresses: "*"
        wal_level: logical
        hot_standby: "on"
        wal_keep_segments: 10
        max_wal_senders: 10
        max_replication_slots: 10
        wal_log_hints: "on"
  initdb:
  - encoding: UTF8
  - locale: C
  - lc-ctype: zh_CN.UTF-8
  - data-checksums
  pg_hba:
  - host replication postgres 0.0.0.0/0 md5
  - host all all 0.0.0.0/0 md5

# PostgreSQL 配置
postgresql:
  listen: 0.0.0.0:5432
  connect_address: 192.168.95.139:5432
  data_dir: /u1/pgsql/data
  bin_dir: /usr/pgsql-12/bin
  config_dir: /u1/pgsql/data
  pgpass: /var/lib/pgsql/.pgpass
  authentication:
    replication:
      username: postgres
      password: postgres123
    superuser:
      username: postgres
      password: postgres123
    rewind:
      username: postgres
      password: postgres123

# 标签配置
tags:
  nofailover: false
  noloadbalance: false
  clonefrom: false
  nosync: false

节点 2 配置(修改对应IP为192.168.95.140)和节点 3 配置(修改对应IP为192.168.95.141)同理,只需更改 namelistenconnect_addresspgpass 配置。

3.4 设置权限和目录
# 在所有节点执行
chown -R postgres.postgres /etc/patroni/
chmod 600 /etc/patroni/patroni_postgresql.yml
chown -R postgres.postgres /tmp/patroni02
3.5 创建 Patroni 系统服务

创建服务文件 (/usr/lib/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/patroni_postgresql.yml
KillMode=process
TimeoutSec=30
Restart=no

[Install]
WantedBy=multi-user.target

启动 Patroni 服务

# 在所有节点执行
systemctl daemon-reload
systemctl enable patroni
systemctl start patroni
3.6 验证集群状态
# 查看集群状态
patronictl -c /etc/patroni/patroni_postgresql.yml list

# 如遇 Python 依赖错误
yum install python3-psycopg2

成功状态示例

+ Cluster: postgresql12 (6965741508141313244) ---------+----+-----------+
| Member    | Host             | Role    | State   | TL | Lag in MB |
+-----------+------------------+---------+---------+----+-----------+
| node1     | 192.168.95.139   | Leader  | running |  1 |           |
| node2     | 192.168.95.140   | Replica | running |  1 |       0.0 |
| node3     | 192.168.95.141   | Replica | running |  1 |       0.0 |
+-----------+------------------+---------+---------+----+-----------+
3.7 手动故障转移测试
# 手动切换 Leader(测试用)
patronictl -c /etc/patroni/patroni_postgresql.yml switchover

高可用组件配置

1. 安装和配置 HAProxy

1.1 安装 HAProxy
# 在所有节点执行
yum install -y haproxy
1.2 配置 HAProxy

配置文件 (/etc/haproxy/haproxy.cfg):

global
    maxconn 100
    log     127.0.0.1 local2

defaults
    log global
    mode tcp
    retries 2
    timeout client 30m
    timeout connect 4s
    timeout server 30m
    timeout check 5s

# 统计页面
listen stats
    mode http
    bind *:7000
    stats enable
    stats uri /

# 主库读写服务
listen pgsql
    mode tcp
    bind *:5000
    option httpchk
    http-check expect status 200
    default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
    server postgresql_192.168.95.139_5432 192.168.95.139:5432 maxconn 100 check port 8008
    server postgresql_192.168.95.140_5432 192.168.95.140:5432 maxconn 100 check port 8008
    server postgresql_192.168.95.141_5432 192.168.95.141:5432 maxconn 100 check port 8008

# 备库只读服务
listen pgsql_read
    mode tcp
    bind *:6000
    option httpchk GET /replica
    http-check expect status 200
    default-server inter 3s fall 3 rise 2 on-marked-down shutdown-sessions
    server postgresql_192.168.95.139_5432 192.168.95.139:5432 maxconn 100 check port 8008
    server postgresql_192.168.95.140_5432 192.168.95.140:5432 maxconn 100 check port 8008
    server postgresql_192.168.95.141_5432 192.168.95.141:5432 maxconn 100 check port 8008
1.3 启动 HAProxy
systemctl enable haproxy
systemctl start haproxy

# 解决端口绑定问题(SELinux)
setsebool -P haproxy_connect_any=1

2. 安装和配置 Keepalived

2.1 安装 Keepalived
# 在 node1 和 node2 上安装
yum install -y keepalived
2.2 配置 Keepalived

node1 配置 (/etc/keepalived/keepalived.conf):

global_defs {
    router_id LVS_DEVEL
}

vrrp_script check_haproxy {
    script "pgrep -x haproxy"
    interval 2
    weight 10
}

vrrp_instance VI_1 {
    state BACKUP             # 备服务器状态
    interface ens33          # 网络接口,根据实际修改
    virtual_router_id 210
    priority 90              # 优先级,node1 设置为 90
    advert_int 1
    track_script {
        check_haproxy
    }
    virtual_ipaddress {
       192.168.95.142        # 虚拟 IP
    }
}

node2 配置(将 priority 改为 80,其他相同)

2.3 启动 Keepalived
systemctl enable keepalived
systemctl start keepalived

# 验证虚拟 IP 配置
ip addr show dev ens33

数据库连接配置

1. 应用数据库配置

根据您的项目 application-dev.yml,当前使用 Oracle 数据库。要切换到 PostgreSQL 高可用集群,需要修改配置:

spring:
  datasource:
    # HAProxy 代理的读写分离配置
    url: jdbc:postgresql://192.168.95.142:5000/postgres
    username: postgres
    password: postgres123
  
    # 多主机 URL 配置(备选方案)
    # 主库连接
    # url: jdbc:postgresql://192.168.95.139:5432,192.168.95.140:5432,192.168.95.141:5432/postgres?targetServerType=primary
  
    # 读写分离配置
    # url: jdbc:postgresql://192.168.95.139:5432,192.168.95.140:5432,192.168.95.141:5432/postgres?targetServerType=preferSecondary&loadBalanceHosts=true

2. 连接字符串配置选项

2.1 JDBC 多主机 URL

连接主库(可写节点)

jdbc:postgresql://192.168.95.139:5432,192.168.95.140:5432,192.168.95.141:5432/postgres?targetServerType=primary

优先连接备库

jdbc:postgresql://192.168.95.139:5432,192.168.95.140:5432,192.168.95.141:5432/postgres?targetServerType=preferSecondary&loadBalanceHosts=true

随机连接任意节点

jdbc:postgresql://192.168.95.139:5432,192.168.95.140:5432,192.168.95.141:5432/postgres?targetServerType=any&loadBalanceHosts=true
2.2 HAProxy 代理配置

读写分离访问

  • 写操作: 192.168.95.142:5000
  • 读操作: 192.168.95.142:6000
  • 状态监控: http://192.168.95.142:7000

高级配置

1. 级联复制配置

1.1 集群内部级联复制

在备库节点添加以下配置:

tags:
  replicatefrom: node2  # 指定从 node2 复制数据
1.2 集群间级联复制

创建灾备集群配置:

bootstrap:
  dcs:
    standby_cluster:
      host: 192.168.234.210    # 上游集群地址
      port: 5432
      primary_slot_name: slot1
      create_replica_methods:
      - basebackup

2. 复制槽配置

在主集群配置中添加复制槽:

bootstrap:
  dcs:
    slots:
      slot1:
        type: physical

监控和维护

1. 集群状态监控

1.1 Patroni 状态查询
# 查看集群详细信息
patronictl -c /etc/patroni/patroni_postgresql.yml list

# 查看成员详情
patronictl -c /etc/patroni/patroni_postgresql.yml query

# 查看配置
patronictl -c /etc/patroni/patroni_postgresql.yml show
1.2 PostgreSQL 状态监控
# 连接数据库查看复制状态
psql -h 192.168.95.139 -U postgres -c "SELECT * FROM pg_stat_replication;"

2. 日志查看

# Patroni 日志
tail -f /tmp/patroni02/patroni.log

# PostgreSQL 日志
tail -f /u1/pgsql/data/log/postgresql-*.log

# etcd 日志
journalctl -u etcd -f

3. 性能优化配置

在 Patroni 配置的 parameters 部分添加优化参数:

postgresql:
  parameters:
    # 内存优化
    shared_buffers: 256MB
    effective_cache_size: 1GB
    work_mem: 4MB
    maintenance_work_mem: 64MB
  
    # 连接优化
    max_connections: 100
  
    # WAL 配置
    wal_buffers: 16MB
    checkpoint_completion_target: 0.9
  
    # 查询优化
    random_page_cost: 1.1
    effective_io_concurrency: 200

故障处理

1. 常见问题解决

1.1 Patroni 启动失败

问题: .pgpass 文件路径错误

# 检查配置文件中的路径设置
pgpass: /var/lib/pgsql/.pgpass  # 正确路径
1.2 集群初始化失败
# 清理数据目录重新初始化
rm -rf /u1/pgsql/data/*
systemctl restart patroni
1.3 HAProxy 启动失败

问题: 端口绑定失败

# 检查 SELinux 设置
setsebool -P haproxy_connect_any=1
# 或关闭 SELinux
setenforce 0
1.4 Keepalived 虚拟IP不生效
# 检查网络接口配置
ip addr show dev ens33

# 检查防火墙设置
firewall-cmd --add-rich-rule='rule family="ipv4" destination address="192.168.95.142" accept'

2. 应急处理流程

2.1 主库故障处理
  1. 确认故障: 检查集群状态

    patronictl -c /etc/patroni/patroni_postgresql.yml list
    
  2. 等待自动故障转移: Patroni 会自动处理

  3. 手动故障转移(如需要):

    patronictl -c /etc/patroni/patroni_postgresql.yml switchover
    
2.2 节点恢复流程
  1. 修复节点: 解决硬件或系统问题
  2. 重启 Patroni:
    systemctl restart patroni
    
  3. 验证同步状态: 确认数据同步完成
2.3 数据恢复流程
# 从备份恢复数据
sudo -u postgres pg_ctl -D /u1/pgsql/data stop
rm -rf /u1/pgsql/data/*
# 恢复备份文件
systemctl start patroni

备份和恢复

1. 自动备份配置

创建备份脚本 (/usr/local/bin/pg_backup.sh):

#!/bin/bash
# PostgreSQL 高可用集群备份脚本

# 备份配置
BACKUP_DIR="/backup/pg"
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=7

# 创建备份目录
mkdir -p $BACKUP_DIR

# 连接到主库进行备份
psql -h 192.168.95.139 -U postgres -c "SELECT pg_start_backup('backup_$DATE');"

# 备份数据文件
tar -czf $BACKUP_DIR/pg_data_$DATE.tar.gz -C /u1/pgsql/data .

# 结束备份
psql -h 192.168.95.139 -U postgres -c "SELECT pg_stop_backup();"

# 清理旧备份
find $BACKUP_DIR -name "pg_data_*.tar.gz" -mtime +$RETENTION_DAYS -delete

echo "Backup completed: pg_data_$DATE.tar.gz"

设置定时任务

chmod +x /usr/local/bin/pg_backup.sh
# 每天凌晨2点执行备份
echo "0 2 * * * /usr/local/bin/pg_backup.sh" | crontab -

2. 恢复操作

# 停止 Patroni
systemctl stop patroni

# 备份当前数据
mv /u1/pgsql/data /u1/pgsql/data.backup

# 恢复数据
mkdir -p /u1/pgsql/data
tar -xzf /backup/pg/pg_data_YYYYMMDD_HHMMSS.tar.gz -C /u1/pgsql/data

# 设置权限
chown -R postgres:postgres /u1/pgsql/data
chmod 700 /u1/pgsql/data

# 启动 Patroni
systemctl start patroni

总结

本部署指南提供了完整的 PostgreSQL 高可用集群部署方案,包含以下核心功能:

  • 高可用性: 基于 Patroni 的自动故障转移
  • 读写分离: HAProxy 代理的读写流量分离
  • 负载均衡: 多节点负载分发
  • 虚拟IP: Keepalived 提供的透明高可用
  • 监控界面: HAProxy 统计页面
  • 扩展性: 支持动态添加节点

生产环境注意事项

  1. 安全配置:

    • 启用 SSL/TLS 加密
    • 配置防火墙规则
    • 设置强密码策略
  2. 性能优化:

    • 根据硬件配置调整参数
    • 监控系统性能指标
    • 定期进行性能评估
  3. 容灾备份:

    • 配置异地备份
    • 定期演练恢复流程
    • 监控备份完整性
  4. 维护计划:

    • 定期更新系统补丁
    • 监控磁盘空间使用
    • 检查系统日志异常

通过以上配置,您可以获得一个稳定、高可用的 PostgreSQL 集群环境。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值