合 PG高可用之主从流复制+keepalived 的高可用
Tags: PG高可用switchoverfailover故障切换
简介
常见的高可用架构:
pg + keepalived:https://www.dbaup.com/pggaokeyongzhizhucongliufuzhikeepalived-degaokeyong.html
pg + pgpool:pgpool-II和pgpoolAdmin的使用
pg + repmgr:PostgreSQL高可用之repmgr(1主2从+1witness)+Pgpool-II实现主从切换+读写分离+负载均衡
pg + Patroni + etcd:PG高可用集群之Patroni + etcd + HAProxy + keepalived + Prometheus + Grafana监控 部署
通过keepalived 来实现 PostgreSQL 数据库的主从自动切换,以达到高可用。当主节点宕机时,从节点可自动切换为主节点,继续对外提供服务。
在这一方案中Keepalived程序主要用来探测PostgreSQL主库是否存活,如果Keepalived主节点或主库故障,Keepalived备节点将接管VIP 并日激活流复制备库.从而实现高可用。
Keepalived的介绍:
环境架构
IP地址 | 操作系统 | 主机名 | 角色 | 端口 | 说明 |
---|---|---|---|---|---|
172.72.6.6 | CentOS 7.6 | lhrpg66 | 主库 | 5433 | 安装postgesql 13.3 + keepalived v1.3.5 |
172.72.6.7 | CentOS 7.6 | lhrpg67 | 从库 | 5433 | 安装postgesql 13.3 + keepalived v1.3.5 |
172.72.6.8 | VIP | 在pg66和pg67之间进行漂移 |
配置主从流复制
主机环境准备
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | -- 创建PG高可用环境专用网络 docker network create --subnet=172.72.6.0/24 pg-network -- 申请主机 docker rm -f lhrpg66 docker run -d --name lhrpg66 -h lhrpg66 \ -p 64306:5433 --net=pg-network --ip 172.72.6.6 \ -v /sys/fs/cgroup:/sys/fs/cgroup \ --privileged=true lhrbest/lhrpgall:2.0 \ /usr/sbin/init docker rm -f lhrpg67 docker run -d --name lhrpg67 -h lhrpg67 \ -p 64307:5433 --net=pg-network --ip 172.72.6.7 \ -v /sys/fs/cgroup:/sys/fs/cgroup \ --privileged=true lhrbest/lhrpgall:2.0 \ /usr/sbin/init [root@docker35 ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a320c1882201 lhrbest/lhrpgall:2.0 "/usr/sbin/init" 23 seconds ago Up 21 seconds 0.0.0.0:64307->5433/tcp, :::64307->5433/tcp lhrpg67 e9c67922b0e8 lhrbest/lhrpgall:2.0 "/usr/sbin/init" 26 seconds ago Up 24 seconds 0.0.0.0:64306->5433/tcp, :::64306->5433/tcp lhrpg66 |
注意:该容器已安装PostgreSQL 13.3,故只需要配置主从即可,安装用户为pg13。
需要关闭其它版本的pg:
systemctl stop pg11
systemctl stop pg12
systemctl stop pg94
systemctl stop pg96
systemctl stop postgresql-13.servicesystemctl disable pg11
systemctl disable pg12
systemctl disable pg94
systemctl disable pg96
systemctl disable postgresql-13.service
主库放开防火墙
1 2 3 4 5 6 7 8 9 | cat << EOF > /pg13/pgdata/pg_hba.conf # TYPE DATABASE USER ADDRESS METHOD local all all trust host all all 127.0.0.1/32 trust host all all 0.0.0.0/0 md5 host replication all 0.0.0.0/0 md5 EOF |
👉 注意添加replication
主库创建复制用户
1 2 3 | su - pg13 psql create user replhr password 'lhr' replication; |
👉 创建用户需要加上replication选项。
在从库对主库进行备份
1 2 3 4 5 | mkdir /bk chown pg13.postgres /bk su - pg13 pg_basebackup -h 172.72.6.6 -p 5433 -U replhr -l bk20220210 -F p -P -R -D /bk |
执行完成后,会产生文件standby.signal,如下:
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 | [pg13@lhrpg67 ~]$ pg_basebackup -h 172.72.6.6 -p 5433 -U replhr -l bk20220210 -F p -P -R -D /bk Password: WARNING: skipping special file "./.s.PGSQL.5433" WARNING: skipping special file "./.s.PGSQL.5433" 23411/23411 kB (100%), 1/1 tablespace [pg13@lhrpg67 ~]$ ll /bk total 260 -rw------- 1 pg13 postgres 209 Feb 10 16:27 backup_label -rw------- 1 pg13 postgres 135710 Feb 10 16:27 backup_manifest drwx------ 5 pg13 postgres 4096 Feb 10 16:27 base -rw------- 1 pg13 postgres 33 Feb 10 16:27 current_logfiles drwx------ 2 pg13 postgres 4096 Feb 10 16:27 global drwx------ 2 pg13 postgres 4096 Feb 10 16:27 pg_commit_ts drwx------ 2 pg13 postgres 4096 Feb 10 16:27 pg_dynshmem -rw------- 1 pg13 postgres 243 Feb 10 16:27 pg_hba.conf -rw------- 1 pg13 postgres 1636 Feb 10 16:27 pg_ident.conf drwx------ 2 pg13 postgres 4096 Feb 10 16:27 pg_log drwx------ 4 pg13 postgres 4096 Feb 10 16:27 pg_logical drwx------ 4 pg13 postgres 4096 Feb 10 16:27 pg_multixact drwx------ 2 pg13 postgres 4096 Feb 10 16:27 pg_notify drwx------ 2 pg13 postgres 4096 Feb 10 16:27 pg_replslot drwx------ 2 pg13 postgres 4096 Feb 10 16:27 pg_serial drwx------ 2 pg13 postgres 4096 Feb 10 16:27 pg_snapshots drwx------ 2 pg13 postgres 4096 Feb 10 16:27 pg_stat drwx------ 2 pg13 postgres 4096 Feb 10 16:27 pg_stat_tmp drwx------ 2 pg13 postgres 4096 Feb 10 16:27 pg_subtrans drwx------ 2 pg13 postgres 4096 Feb 10 16:27 pg_tblspc drwx------ 2 pg13 postgres 4096 Feb 10 16:27 pg_twophase -rw------- 1 pg13 postgres 3 Feb 10 16:27 PG_VERSION drwx------ 3 pg13 postgres 4096 Feb 10 16:27 pg_wal drwx------ 2 pg13 postgres 4096 Feb 10 16:27 pg_xact -rw------- 1 pg13 postgres 314 Feb 10 16:27 postgresql.auto.conf -rw------- 1 pg13 postgres 28184 Feb 10 16:27 postgresql.conf -rw------- 1 pg13 postgres 0 Feb 10 16:27 standby.signal |
👉 在PG12之前,-R备份结束之后会自动生成recovery.conf文件,用来做流复制判断主从同步的信息。但是从PG12开始,这个文件已经不需要了。只需要在参数文件postgresql.conf中配置primary_conninfo参数即可。
还原从库
1 2 3 | -- 关闭从库,删除从库的数据文件,并且将备份文件覆盖从库的数据文件 pg_ctl stop cp -r /bk/* /pg13/pgdata/ |
修改从库primary_conninfo参数
1 2 3 4 5 6 | cat >> /pg13/pgdata/postgresql.conf <<"EOF" primary_conninfo = 'host=172.72.6.6 port=5433 user=replhr password=lhr' EOF |
启动从库
1 | pg_ctl start |
主库进程:
1 2 3 4 5 6 7 8 9 10 11 | [root@lhrpg66 /]# ps -ef|grep pg13 pg13 1053 0 0 16:16 ? 00:00:00 /pg13/pg13/bin/postgres -D /pg13/pgdata -p 5433 pg13 1054 1053 0 16:16 ? 00:00:00 postgres: logger pg13 1056 1053 0 16:16 ? 00:00:00 postgres: checkpointer pg13 1057 1053 0 16:16 ? 00:00:00 postgres: background writer pg13 1058 1053 0 16:16 ? 00:00:00 postgres: walwriter pg13 1059 1053 0 16:16 ? 00:00:00 postgres: autovacuum launcher pg13 1060 1053 0 16:16 ? 00:00:00 postgres: stats collector pg13 1061 1053 0 16:16 ? 00:00:00 postgres: logical replication launcher pg13 1827 1053 0 16:29 ? 00:00:00 postgres: walsender replhr 172.72.6.7(51662) streaming 0/3000148 root 2024 551 0 16:32 pts/0 00:00:00 grep --color=auto pg13 |
从库进程:
1 2 3 4 5 6 7 8 9 | [root@lhrpg67 /]# ps -ef|grep pg13 pg13 1900 0 0 16:29 ? 00:00:00 /pg13/pg13/bin/postgres pg13 1901 1900 0 16:29 ? 00:00:00 postgres: logger pg13 1902 1900 0 16:29 ? 00:00:00 postgres: startup recovering 000000010000000000000003 pg13 1903 1900 0 16:29 ? 00:00:00 postgres: checkpointer pg13 1904 1900 0 16:29 ? 00:00:00 postgres: background writer pg13 1905 1900 0 16:29 ? 00:00:00 postgres: stats collector pg13 1906 1900 0 16:29 ? 00:00:00 postgres: walreceiver streaming 0/3000148 root 2186 540 0 16:32 pts/0 00:00:00 grep --color=auto pg13 |
查询复制状态
1 2 3 4 5 6 7 8 9 10 11 12 | -- 主库查看wal日志发送状态 select * from pg_stat_replication; -- 从库查看wal日志接收状态 select * from pg_stat_wal_receiver; -- 也可以通过该名称查看 pg_controldata | grep state -- 也可以查看这个,主库是f代表false ;备库是t,代表true select pg_is_in_recovery(); |
主库查询复制状态:
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 | C:\Users\lhrxxt>psql -U postgres -h 192.168.66.35 -p 64306 Password for user postgres: psql (14.0, server 13.3) Type "help" for help. postgres=# select * from pg_stat_replication; pid | usesysid | usename | application_name | client_addr | client_hostname | client_port | backend_start | backend_xmin | state | sent_lsn | write_lsn | flush_lsn | replay_lsn | write_lag | flush_lag | replay_lag | sync_priority | sync_state | reply_time -----+----------+---------+------------------+-------------+-----------------+-------------+-------------------------------+--------------+-----------+-----------+-----------+-----------+------------+-----------+-----------+------------+---------------+------------+------------------------------- 623 | 16430 | replhr | walreceiver | 172.72.6.7 | | 51676 | 2022-02-10 16:37:28.351635+08 | | streaming | 0/3000060 | 0/3000060 | 0/3000060 | 0/3000060 | | | | 0 | async | 2022-02-10 16:38:58.583056+08 (1 row) postgres=# \x Expanded display is on. postgres=# select * from pg_stat_replication; -[ RECORD 1 ]----+------------------------------ pid | 623 usesysid | 16430 usename | replhr application_name | walreceiver client_addr | 172.72.6.7 client_hostname | client_port | 51676 backend_start | 2022-02-10 16:37:28.351635+08 backend_xmin | state | streaming sent_lsn | 0/3000060 write_lsn | 0/3000060 flush_lsn | 0/3000060 replay_lsn | 0/3000060 write_lag | flush_lag | replay_lag | sync_priority | 0 sync_state | async reply_time | 2022-02-10 16:39:18.625797+08 |
pg_stat_replication是一个视图,主要用于监控PG流复制情况。在这个系统视图中每个记录只代表一个slave。因此,可以看到谁处于连接状态,在做什么任务。pg_stat_replication也是检查slave是否处于连接状态的一个好方法。
每个字段代码的含义:
• pid: 这代表负责流连接的wal_sender进程的进程ID。例如“postgres: walsender replhr 172.72.6.3(40056) streaming 0/7000148”。
• usesysid: 每个内部用户都有一个独一无二的编号。该系统的工作原理很像UNIX。 usesysid 是 (PostgreSQL) 用户连接到系统的唯一标识符。
• usename: (不是用户名, 注意少了 r),它存储与用户相关的 usesysid 的名字。这是客户端放入到连接字符串中的东西。
• application_name:这是同步复制的通常设置。它可以通过连接字符串传递到master。
• client_addr: 它会告诉您流连接从何而来。它拥有客户端的IP地址。
• client_hostname: 除了客户端的IP,您还可以这样做,通过它的主机名来标识客户端。您可以通过master上的postgresql.conf中的log_hostname启用DNS反向查找。
• client_port: 这是客户端用来和WALsender进行通信使用的TPC端口号。 如果不本地UNIX套接字被使用了将显示-1。
• backend_start: 它告诉我们slave什么时间创建了流连接。