基于PGPool的双机集群如下图所示:pg主节点和备节点实现流复制热备,pgpool1,pgpool2作为中间件,将主备pg节点加入集群,实现读写分离,负载均衡和HA故障自动切换。两pgpool节点可以委托一个虚拟ip节点作为应用程序访问的地址,两节点之间通过watchdog进行监控,当pgpool1宕机时,pgpool2会自动接管虚拟ip继续对外提供不间断服务。
1.主机规划
192.168.20.201 redis01
192.168.20.202 redis02
192.168.20.203 vip
2.配置主机ssh互信
ssh-keygen -t rsa
ssh-copy-id -i ~/.ssh/id_rsa.pub redis02
3.安装pgpool
wget http://www.pgpool.net/mediawiki/images/pgpool-II-4.1.1.tar.gz
[postgres@redis01 ~]$ tar -zxf pgpool-II-4.1.0.tar.gz
./configure --prefix=/u01/pgpool --with-pgsql=/u01/pgsql
make && make install
4.配置pgpool
4.1配置环境变量
pgpool装在了postgres账户下,在该账户中添加环境变量,master,slave节点都执行。
[postgres@redis01 ~]$ cat .bash_profile
# .bash_profile
export PGHOME=/u01/pgsql
export PGDATA=/u01/pgsql/data
export PGPOOLHOME=/u01/pgpool
export PGPASSFILE=/u01/pgsql/data/.pgpass
export PATH=$PATH:$HOME/bin:$PGHOME/bin:$PGPOOLHOME/bin
export LD_LIBRARY_PATH=$PGHOME/lib:$PGPOOLHOME/lib
4.2配置pool_hba.conf
pool_hba.conf是对登录用户进行验证的,要和pg的pg_hba.conf保持一致,要么都是trust,要么都是md5验证方式,这里采用了md5验证方式如下设置:
# IPv4 local connections:
host all all 127.0.0.1/32 trust
host postgres postgres 192.168.20.0/24 md5
host postgres rep 192.168.20.0/24 md5
host all all 0.0.0.0/0 md5
# IPv6 local connections:
host all all ::1/128 trust
# Allow replication connections from localhost, by a user with the
# replication privilege.
local replication all trust
host replication all 127.0.0.1/32 trust
host replication rep 192.168.20.0/24 md5
host replication all ::1/128 trust
4.3配置pcp.conf
pcp.conf配置用于pgpool自己登陆管理使用的,一些操作pgpool的工具会要求提供密码等,配置如下:
pg_md5 posgres
[postgres@redis01 etc]$ cat pcp.conf
# USERID:MD5PASSWD
postgres:e8a48653851e28c69d0506508fb27fc5
#pcp.conf是pgpool管理器自己的用户名和密码,用于管理集群
pg_md5 -p -m -u postgres pool_passwd
#数据库登录用户是postgres,这里输入登录密码,不能出错
#输入密码后,在pgpool/etc目录下会生成一个pool_passwd文件
4.4配置系统命令权限
配置 ifconfig, arping 执行权限 ,执行failover_stream.sh需要用到,可以让其他普通用户执行。
chmod u+s /sbin/ip
chmod u+s /usr/sbin/arping
4.5配置pgpool.conf
后台连接设置
# - Backend Connection Settings -
backend_hostname0 = 'redis01'
backend_port0 = 5432
backend_weight0 = 1
backend_data_directory0 = '/u01/pgsql/data'
backend_flag0 = 'ALLOW_TO_FAILOVER'
backend_application_name0 = 'server1'
backend_hostname1 = 'redis02'
backend_port1 = 5432
backend_weight1 = 1
backend_data_directory1 = '/u01/pgsql/data'
backend_flag1 = 'ALLOW_TO_FAILOVER'
backend_application_name1 = 'server2'
负载均衡
load_balance_mode = on
postgres流复制
master_slave_mode = on
master_slave_sub_mode = 'stream'
健康检查设置
#------------------------------------------------------------------------------
# HEALTH CHECK GLOBAL PARAMETERS
#------------------------------------------------------------------------------
health_check_period = 10
health_check_timeout = 20
health_check_user = 'postgres'
health_check_password = 'postgres'
health_check_database = ''
health_check_max_retries = 0
health_check_retry_delay = 1
connect_timeout = 10000
灾备切换设置
failover_command = '/u01/pgpool/failover_stream.sh %H %h'
# Executes this command at failover
# Special values:
# %d = failed node id
# %h = failed node host name
# %p = failed node port number
# %D = failed node database cluster path
# %m = new master node id
# %H = new master node hostname
# %M = old master node id
# %P = old primary node id
# %r = new master port number
# %R = new master database cluster path
# %N = old primary node hostname
# %S = old primary node port number
# %% = '%' character
开启看门狗
#------------------------------------------------------------------------------
# WATCHDOG
#------------------------------------------------------------------------------
# - Enabling -
use_watchdog = on
# -Connection to up stream servers -
trusted_servers = '192.168.20.201,192.168.20.202'
ping_path = '/bin'
# - Watchdog communication Settings -
wd_hostname = 'redis01'
wd_port = 9000
wd_priority = 1
wd_authkey = ''
wd_ipc_socket_dir = '/tmp'
配置vip
# - Virtual IP control Setting -
delegate_IP = '192.168.20.205'
if_cmd_path = '/sbin'
if_up_cmd = ' /sbin/ip addr add $_IP_$/24 dev eth2 label eth2:0'
if_down_cmd = '/sbin/ip addr del $_IP_$/24 dev eth2'
arping_path = '/usr/sbin'
arping_cmd = '/usr/sbin/arping -U $_IP_$ -w 1 -I eth2'
其他pgpool连接设置
# - Other pgpool Connection Settings -
other_pgpool_hostname0 = 'redis02'
other_pgpool_port0 =9999
other_wd_port0 = 9000
4.6配置failover_stream.sh脚本
[postgres@redis01 pgpool]$ cat failover_stream.sh
#! /bin/sh
# Failover command for streaming replication.
# Arguments: $1: new master hostname.
new_master=$1
old_master=$2
RECOVERYCONF=$PGDATA/recovery.conf
touch_command="touch $RECOVERYCONF"
trigger_command="$PGHOME/bin/pg_ctl promote -D $PGDATA"
delrecovery_command="rm -f $PGDATA/recovery.done && rm -f $PGDATA/recovery.conf"
echo1_cmd="echo -e \" primary_conninfo = 'host=$new_master port=5432 user=rep password=rep passfile=''/u01/pgsql/data/.pgpass''' \" >> $PGDATA/recovery.conf"
echo2_cmd="echo -e \" recovery_target_timeline = 'latest' \" >> $PGDATA/recovery.conf"
echo3_cmd="echo -e \" standby_mode = 'on' \" >> $PGDATA/recovery.conf"
# Prompte standby database.
/usr/bin/ssh -T $new_master $trigger_command
# create recovery.conf
/usr/bin/ssh -T $old_master $delrecovery_command
/usr/bin/ssh -T $old_master $touch_command
/usr/bin/ssh -T $old_master $echo3_cmd
/usr/bin/ssh -T $old_master $echo1_cmd
/usr/bin/ssh -T $old_master $echo2_cmd
exit 0;
检测到postgresql down机以后把standby转成primary模式可读写,在down机的主机生成recovery.conf,down机的postgresql启动起来以后自动转成standby。
4.7启动pgpool
启动pgpool以前先启动postgresql, postgresql已配置好流复制
启动postgressql
pg_ctl start
查看流复制
[postgres@redis01 etc]$ psql -c 'SELECT client_addr,application_name,sync_state FROM pg_stat_replication;'
client_addr | application_name | sync_state
----------------+------------------+------------
192.168.20.202 | walreceiver | sync
启动pgpool
pgpool -n -D > /u01/pgpool/log/pgpool.log 2>&1 &
查看pgpool节点
[postgres@redis01 etc]$ psql -h 192.168.20.205 -p 9999 -c 'show pool_nodes'
node_id | hostname | port | status | lb_weight | role | select_cnt | load_balance_node | replication_delay | replication_state | replication_sync_state | last_status_change
---------+----------+------+--------+-----------+---------+------------+-------------------+-------------------+-------------------+------------------------+---------------------
0 | redis01 | 5432 | up | 0.500000 | primary | 0 | true | 0 | | | 2020-02-23 22:04:41
1 | redis02 | 5432 | up | 0.500000 | standby | 0 | false | 0 | | | 2020-02-23 22:04:41
查看vip
[postgres@redis01 ~]$ ifconfig -a
eth1 Link encap:Ethernet HWaddr 08:00:27:E9:92:7B
inet addr:10.0.2.15 Bcast:10.0.2.255 Mask:255.255.255.0
inet6 addr: fe80::a00:27ff:fee9:927b/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:11 errors:0 dropped:0 overruns:0 frame:0
TX packets:19 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:1921 (1.8 KiB) TX bytes:1968 (1.9 KiB)
eth2 Link encap:Ethernet HWaddr 08:00:27:CF:77:EB
inet addr:192.168.20.201 Bcast:192.168.20.255 Mask:255.255.255.0
inet6 addr: fe80::a00:27ff:fecf:77eb/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:32488 errors:0 dropped:0 overruns:0 frame:0
TX packets:31045 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:3737971 (3.5 MiB) TX bytes:3848610 (3.6 MiB)
eth2:0 Link encap:Ethernet HWaddr 08:00:27:CF:77:EB
inet addr:192.168.20.205 Bcast:0.0.0.0 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
5.演示postgresql down机
[postgres@redis01 ~]$ pg_ctl stop -m fast
waiting for server to shut down..... done
server stopped
redis01 postgressql日志
2020-02-23 22:45:21.402 CST [2577] LOG: received fast shutdown request
2020-02-23 22:45:21.682 CST [2577] LOG: aborting any active transactions
2020-02-23 22:45:21.682 CST [2577] LOG: background worker "logical replication launcher" (PID 2586) exited with exit code 1
2020-02-23 22:45:21.683 CST [2580] LOG: shutting down
2020-02-23 22:45:23.174 CST [2577] LOG: database system is shut down
redis02 postgressql日志
2020-02-23 22:45:23.174 CST [12119] FATAL: could not connect to the primary server: could not connect to server: Connection refused
Is the server running on host "redis01" (192.168.20.201) and accepting
TCP/IP connections on port 5432?
2020-02-23 22:45:28.180 CST [12126] FATAL: could not connect to the primary server: could not connect to server: Connection refused
Is the server running on host "redis01" (192.168.20.201) and accepting
TCP/IP connections on port 5432?
2020-02-23 22:45:31.395 CST [3584] LOG: received promote request
2020-02-23 22:45:31.395 CST [3584] LOG: redo done at 0/26000028
2020-02-23 22:45:31.405 CST [3584] LOG: selected new timeline ID: 12
2020-02-23 22:45:32.389 CST [3584] LOG: archive recovery complete
2020-02-23 22:45:32.402 CST [3582] LOG: database system is ready to accept connections
查看主备
[postgres@redis02 ~]$ pg_controldata|grep cluster
Database cluster state: in production
[postgres@redis02 ~]$ psql -c 'SELECT client_addr,application_name,sync_state FROM pg_stat_replication;'
client_addr | application_name | sync_state
-------------+------------------+------------
(0 rows)
Redis02主机上的postgressql数据库直接从standby转成primary
查看pgpool集群
[postgres@redis01 pgpool]$ psql -h 192.168.20.205 -p 9999 -c 'show pool_nodes'
node_id | hostname | port | status | lb_weight | role | select_cnt | load_balance_node | replication_delay | replication_state | replication_sync_state | last_status_change
---------+----------+------+--------+-----------+---------+------------+-------------------+-------------------+-------------------+------------------------+---------------------
0 | redis01 | 5432 | down | 0.500000 | standby | 0 | false | 0 | | | 2020-02-23 22:45:33
1 | redis02 | 5432 | up | 0.500000 | primary | 0 | true | 0 | | | 2020-02-23 22:45:33
(2 rows)
从pgpool 来看也是把Redis02主机上的postgressql数据库直接从standby转成primary
启动down机的主节点;启动起来以后转成standby
[postgres@redis01 pgpool]$ pg_ctl start
waiting for server to start....2020-02-23 22:58:00.891 CST [9600] LOG: listening on IPv4 address "192.168.20.201", port 5432
2020-02-23 22:58:00.897 CST [9600] LOG: listening on Unix socket "/tmp/.s.PGSQL.5432"
2020-02-23 22:58:00.912 CST [9600] LOG: redirecting log output to logging collector process
2020-02-23 22:58:00.912 CST [9600] HINT: Future log output will appear in directory "log".
done
server started
[postgres@redis02 ~]$ psql -c 'SELECT client_addr,application_name,sync_state FROM pg_stat_replication;'
client_addr | application_name | sync_state
----------------+------------------+------------
192.168.20.201 | walreceiver | sync
(1 row)
down机的节点加入pgpool集群
[postgres@redis01 pgpool]$ pcp_attach_node -d -U postgres -h 192.168.20.205 -p 9898 -n 0
Password:
DEBUG: recv: tos="m", len=8
DEBUG: recv: tos="r", len=21
DEBUG: send: tos="C", len=6
DEBUG: recv: tos="c", len=20
pcp_attach_node -- Command Successful
DEBUG: send: tos="X", len=4
[postgres@redis01 pgpool]$ psql -h 192.168.20.205 -p 9999 -c 'show pool_nodes'
node_id | hostname | port | status | lb_weight | role | select_cnt | load_balance_node | replication_delay | replication_state | replication_sync_state | last_status_change
---------+----------+------+--------+-----------+---------+------------+-------------------+-------------------+-------------------+------------------------+---------------------
0 | redis01 | 5432 | up | 0.500000 | standby | 0 | true | 0 | | | 2020-02-23 23:00:11
1 | redis02 | 5432 | up | 0.500000 | primary | 0 | false | 0 | | | 2020-02-23 22:45:33
(2 rows)
到此灾备演练完毕。