用 Patroni 打造 PostgreSQL 高可用性:从零到稳如磐石

欢迎踏入 PostgreSQL 高可用性(HA)的精彩世界!在业务场景中,数据库的持续可用性是至关重要的,任何中断都可能引发严重后果。今天,我们将聚焦 Patroni,一个强大的开源工具,帮助您构建一个自动故障转移、自我修复的 PostgreSQL 高可用性集群。本文将以通俗易懂、循序渐进的教学风格,带您了解 Patroni 如何实现高可用性,核心配置步骤,以及如何在实践中确保数据库“永不宕机”。无论您是数据库新手还是经验丰富的 DBA,这篇文章都将为您提供清晰的指引!

类比讲解:Patroni 就像一支训练有素的消防队。PostgreSQL 节点是消防员,分布式配置存储(DCS)是指挥中心,HAProxy 是报警电话,而 Patroni 确保当火灾(主节点故障)发生时,备用消防员(从节点)迅速接管,扑灭火焰(服务中断),让城市(业务)安全无忧!

1. Patroni 如何实现高可用性?

1.1 Patroni 的核心机制

Patroni 是一个基于 Python 的工具,结合 PostgreSQL 的**流复制(Streaming Replication)**和分布式配置存储(DCS),实现高可用性。它的核心机制包括:

  • 自动故障转移:当主节点(Primary)故障时,Patroni 使用分布式共识算法(通过 DCS,如 etcd)选举一个从节点(Replica)为主节点,确保服务不中断。
  • 节点健康监控:Patroni 在每个节点运行,定期检查 PostgreSQL 的状态(如复制延迟、运行状态),并通过 REST API 报告。
  • 动态配置管理:通过 DCS(如 etcd、Consul、ZooKeeper)存储集群状态(如主节点信息、配置),确保所有节点保持一致。
  • 负载均衡:结合 HAProxy 或 PgBouncer,Patroni 提供统一的访问入口,写请求路由到主节点,读请求分发到从节点。
  • 自我修复:故障节点恢复后,Patroni 自动重新初始化并加入集群,使用 pg_rewind 修复数据不一致。

类比讲解:Patroni 是集群的“心脏起搏器”。当心脏(主节点)停跳,起搏器迅速激活备用电源(从节点),并通过电线(DCS)协调节奏,确保心脏(服务)继续跳动!

1.2 为什么 Patroni 适合高可用性?

相比 PostgreSQL 原生流复制,Patroni 解决了以下痛点:

  • 无自动故障转移:原生复制需要手动切换主节点。
  • 节点恢复复杂:故障节点需手动重新配置。
  • 缺乏统一管理:原生工具无法监控集群状态。

Patroni 的优势:

  • 自动化:故障转移和恢复全自动,减少人工干预。
  • 灵活性:支持多种 DCS(etcd、Consul、ZooKeeper、Kubernetes)。
  • 可扩展性:轻松添加从节点,提升读性能。
  • 健壮性:集成备份工具(如 pgBackRest),确保数据安全。

教学小贴士:Patroni 就像自动驾驶系统。您只需设定目的地(高可用性),它会自动导航(故障转移)、避障(节点恢复),让旅程(数据库服务)安全顺畅!

2. Patroni 高可用性架构

一个典型的 Patroni 高可用性集群包括:

  • PostgreSQL 节点:一个主节点(写)和多个从节点(读),通过流复制同步。
  • Patroni 代理:运行在每个节点,管理 PostgreSQL 生命周期(启动、停止、故障转移)。
  • 分布式配置存储(DCS):如 etcd,存储集群状态和锁机制。
  • 负载均衡器:HAProxy 路由写请求到主节点,读请求到从节点。
  • 备份工具(可选):pgBackRest 提供备份和点对恢复(PITR)。

架构示意图

客户端 <-> HAProxy <-> [主节点 + Patroni] <-> [从节点 + Patroni]
                        |                         |
                        +-------> etcd <----------+
                          (分布式配置存储)

类比讲解:Patroni 集群像一个智能厨房。PostgreSQL 节点是厨师,Patroni 是主厨,etcd 是食谱,HAProxy 是服务员,引导客人(请求)到正确的厨师(节点)。

3. 配置 Patroni 高可用性集群

以下是搭建一个简单 Patroni 集群的步骤,基于 Ubuntu 20.04,包含 2 个 PostgreSQL 节点(node1: 192.168.1.101, node2: 192.168.1.102)和 1 个 etcd/HAProxy 节点(192.168.1.103)。

3.1 准备工作

  • 操作系统:Ubuntu 20.04。
  • 节点:3 台服务器,IP 如上。
  • 端口:开放 5432(PostgreSQL)、8008(Patroni API)、2379/2380(etcd)、5000/5001(HAProxy)。
  • 软件:PostgreSQL 14、Patroni、etcd、HAProxy。

教学小贴士:准备工作像布置教室。确保每个学生(节点)有课本(软件)和座位(网络配置),才能开始上课(集群搭建)!

3.2 安装软件

在所有节点上执行:

  1. 安装 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
    
  2. 安装 Patroni 和依赖

    1
    2
    
    sudo apt install -y python3 python3-pip
    sudo pip3 install patroni python-etcd psycopg2-binary
    
  3. 停止默认 PostgreSQL

    1
    2
    
    sudo systemctl stop postgresql
    sudo systemctl disable postgresql
    

在 etcd/HAProxy 节点(192.168.1.103): 4. 安装 etcd 和 HAProxy

1
sudo apt install -y etcd haproxy

3.3 配置 etcd

In 192.168.1.103 上:

  1. 编辑 etcd 配置文件(/etc/default/etcd):

    1
    
    sudo vi /etc/default/etcd
    

    配置单节点 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"
    
  2. 启动 etcd

    1
    2
    
    sudo systemctl restart etcd
    sudo systemctl enable etcd
    
  3. 验证

    1
    
    etcdctl member list
    

类比讲解:etcd 是集群的“指挥塔”,记录谁是队长(主节点)。配置 etcd 就像调试对讲机,确保指令清晰传达!

3.4 配置 Patroni

在 node1 和 node2 上:

  1. 创建数据目录

    1
    2
    3
    
    sudo mkdir -p /data/pgsql
    sudo chown postgres:postgres /data/pgsql
    sudo chmod 700 /data/pgsql
    
  2. 创建 Patroni 配置文件(/etc/patroni.yml): 在 node1 (192.168.1.101):

    1
    2
    
    sudo mkdir /etc/patroni
    sudo vi /etc/patroni/patroni.yml
    

    添加:

     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
    
    scope: postgres
    name: node1
    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
        maximum_lag_on_failover: 1048576
      postgresql:
        use_pg_rewind: true
        initdb:
        - encoding: UTF8
        - data-checksums
        pg_hba:
        - host replication replicator 192.168.1.0/24 md5
        - host all all 0.0.0.0/0 md5
    postgresql:
      listen: 192.168.1.101:5432
      connect_address: 192.168.1.101:5432
      data_dir: /data/pgsql
      authentication:
        replication:
          username: replicator
          password: replicator
        superuser:
          username: postgres
          password: supersecret
    

    在 node2 (192.168.1.102),复制并修改:

    • name: node2
    • restapi.listenconnect_address:改为 192.168.1.102:8008
    • postgresql.listenconnect_address:改为 192.168.1.102:5432
  3. 设置权限

    1
    2
    
    sudo chown postgres:postgres /etc/patroni/patroni.yml
    sudo chmod 600 /etc/patroni/patroni.yml
    
  4. 创建 Patroni 服务

    1
    
    sudo vi /etc/systemd/system/patroni.service
    

    添加:

    [Unit]
    Description=Patroni PostgreSQL Cluster
    After=network.target
    [Service]
    User=postgres
    Group=postgres
    ExecStart=/usr/local/bin/patroni /etc/patroni.yml
    Restart=on-failure
    [Install]
    WantedBy=multi-user.target
    
  5. 启动 Patroni

    1
    2
    3
    
    sudo systemctl daemon-reload
    sudo systemctl enable patroni
    sudo systemctl start patroni
    

3.5 配置 HAProxy

在 192.168.1.103 上:

  1. 编辑 HAProxy 配置文件(/etc/haproxy/haproxy.cfg):

    1
    
    sudo vi /etc/haproxy/haproxy.cfg
    

    添加:

    global
        maxconn 1000
        user haproxy
        group haproxy
    defaults
        mode tcp
        timeout connect 5000ms
        timeout client 50000ms
        timeout server 50000ms
    frontend postgres_write
        bind *:5000
        mode tcp
        option httpchk GET /master
        default_backend postgres_write_backend
    backend postgres_write_backend
        mode tcp
        option httpchk GET /master
        server node1 192.168.1.101:5432 check port 8008
        server node2 192.168.1.102:5432 check port 8008
    frontend postgres_read
        bind *:5001
        mode tcp
        default_backend postgres_read_backend
    backend postgres_read_backend
        mode tcp
        balance roundrobin
        server node1 192.168.1.101:5432
        server node2 192.168.1.102:5432
    
  2. 重启 HAProxy

    1
    2
    
    sudo systemctl restart haproxy
    sudo systemctl enable haproxy
    

3.6 验证集群

  1. 检查状态

    1
    
    sudo -u postgres patronictl -c /etc/patroni.yml list
    

    输出示例:

    + Cluster: postgres ---+----+-----------+
    | Member | Host            | Role   | State   | TL | Lag |
    +--------+-----------------+--------+---------+----+-----+
    | node1  | 192.168.1.101   | Leader | running | 1  |     |
    | node2  | 192.168.1.102   | Replica| running | 1  | 0   |
    +--------+-----------------+--------+---------+----+-----+
    
  2. 测试连接

    1
    
    psql -h 192.168.1.103 -p 5000 -U postgres
    
  3. 模拟故障转移: 停止 node1 的 Patroni:

    1
    
    sudo systemctl stop patroni
    

    再次检查状态,node2 应成为 Leader。

教学小贴士:配置 Patroni 像组装模型飞机。每个零件(etcd、Patroni、HAProxy)必须精确对接,试飞(验证)确保飞机(集群)平稳起飞!

4. 优化与注意事项

4.1 优化建议

  • 多节点 DCS:部署 3 或 5 个 etcd 节点,避免单点故障:
    1
    2
    
    etcd:
      hosts: 192.168.1.103:2379,192.168.1.104:2379,192.168.1.105:2379
    
  • 备份:集成 pgBackRest:
    1
    2
    
    sudo apt install pgbackrest
    sudo pgbackrest --stanza=pg_cluster backup
    
  • 监控:使用 Prometheus 或 PMM 监控复制延迟和节点状态。
  • 复制延迟:调整 maximum_lag_on_failover 和 WAL 参数:
    1
    2
    3
    4
    
    postgresql:
      parameters:
        wal_buffers: 16MB
        max_wal_senders: 10
    

4.2 注意事项

  • 防火墙:限制公网访问,仅开放必要端口。
  • 日志检查:故障时查看 Patroni 日志:
    1
    
    journalctl -u patroni
    
  • 统计信息:定期运行 ANALYZE 优化查询计划。
  • 权限:确保 pg_hba.conf 允许复制:
    1
    
    host replication replicator 192.168.1.0/24 md5
    

类比讲解:优化 Patroni 像调校赛车。调整引擎(etcd)、加装导航(监控)、检查轮胎(备份),让赛车(集群)跑得更快、更稳!

5. 总结与进阶建议

通过本文,您学会了如何使用 Patroni 实现 PostgreSQL 高可用性,包括核心机制、配置步骤和优化技巧。Patroni 通过自动故障转移、分布式共识和负载均衡,确保数据库服务持续可用。

进阶建议

  • 阅读 Patroni 文档:patroni.readthedocs.io.
  • 实践多节点 etcd 和 pgBackRest 配置。
  • 使用 REST API 开发监控脚本:
    1
    
    curl http://192.168.1.101:8008/health
    
  • 探索 Kubernetes 集成,简化 Patroni 部署。

希望这篇文章为您的 PostgreSQL 高可用性之旅提供实用指导!欢迎在博客评论区分享您的 Patroni 经验!

评论 0