备注: watchdog可以避免 pgpool 的单点故障。
参考文章:http://francs3.blog.163.com/blog/static/4057672720149285445881/
一、准备工作
1、pgpool的安装工作,可以参考我另外一篇pgpoll连接池模式
2、pg9.5的主备配置,可以参考主备的配置
3、ssh-keygen信任关系,参考pg9.5主备中的,基本就是双机root\postgres两个用户互相信任,但是千万别忘了一自己信任自己,例如failer_command他会ssh 新pri主机IP,如果不信任自己。。。登着郁闷吧
4、依赖包apt-get install arping
5、修改两边的/etc/hosts,否则,在failer_command执行的时候会找不到最新主服务的HOSTNAME:
192.168.180.222 master
192.168.180.223 slave
二、数据库recovery.conf 配置(apt-get的目录在/var/lib/postgresql/9.5/main)
restore_command = 'cp /var/lib/postgresql/archive/%f %p' standby_mode = 'on' primary_conninfo= 'host=192.168.180.222 port=5432 user=postgres password=postgres' trigger_file='/tmp/trigger_file0'
备注: primary_conninfo 的 host 分别配置对端 host IP
三、master的pgpool.conf配置
grep ^[a-z] pgpool.conf
listen_addresses = '*' #所有地址都可以访问 port = 9999 #端口自定义 socket_dir = '/var/run/postgresql' #pg建议放在/var/run/postgresql listen_backlog_multiplier = 2 serialize_accept = off pcp_listen_addresses = '*' pcp_port = 9898 pcp_socket_dir = '/var/run/postgresql' #pg建议放在/var/run/postgresql backend_hostname0 = '192.168.180.222' #配置数据节点 backend_port0 = 5432 backend_weight0 = 1 backend_data_directory0 = '/var/lib/postgresql/9.5/main' backend_flag0 = 'ALLOW_TO_FAILOVER' backend_hostname1 = '192.168.180.223' #配置数据节点 backend_port1 = 5432 backend_weight1 = 1 backend_data_directory1 = '/var/lib/postgresql/9.5/main' backend_flag1 = 'ALLOW_TO_FAILOVER' enable_pool_hba = on pool_passwd = 'pool_passwd' authentication_timeout = 60 ssl = off num_init_children = 32 max_pool = 4 child_life_time = 300 child_max_connections = 0 connection_life_time = 450 client_idle_limit = 300 log_destination = 'syslog' log_line_prefix = '%t: pid %p: ' log_connections = off log_hostname = off log_statement = off log_per_node_statement = off log_standby_delay = 'none' syslog_facility = 'LOCAL0' syslog_ident = 'pgpool' debug_level = 0 pid_file_name = '/var/run/pgpool/pgpool.pid' logdir = '/tmp' connection_cache = on reset_query_list = 'ABORT; DISCARD ALL' replication_mode = off replicate_select = off insert_lock = off lobj_lock_table = '' replication_stop_on_mismatch = off failover_if_affected_tuples_mismatch = off load_balance_mode = on ignore_leading_white_space = on white_function_list = '' black_function_list = 'currval,lastval,nextval,setval' database_redirect_preference_list = '' app_name_redirect_preference_list = '' allow_sql_comments = off master_slave_mode = on # 设置流复制模式 master_slave_sub_mode = 'stream' # 设置流复制模式,采用postgresql自身的流复制 sr_check_period = 5 sr_check_user = 'postgres' sr_check_password = 'postgres' sr_check_database = 'postgres' delay_threshold = 0 follow_master_command = '' health_check_period = 1 #健康检查开启 health_check_timeout = 10 #10秒超时就算挂了 health_check_user = 'postgres' #检查的用户 health_check_password = 'postgres' #检查的密码 health_check_database = 'postgres' #检查的数据库 health_check_max_retries = 1 #最大重试次数 health_check_retry_delay = 2 #每次重试延迟 connect_timeout = 10000 failover_command = '/usr/lib/postgresql/9.5/bin/failover_stream.sh %d %H /tmp/trigger_file0' #配置 failover 脚本,脚本内容下面会贴出。 failback_command = '' fail_over_on_backend_error = on search_primary_node_timeout = 10 recovery_user = 'postgres' recovery_password = 'postgres' recovery_1st_stage_command = '' recovery_2nd_stage_command = '' recovery_timeout = 90 client_idle_limit_in_recovery = 0 use_watchdog = on #使用watch dog trusted_servers = '' ping_path = '/bin' wd_hostname = '192.168.180.222' #配置watch dog绑定的IP wd_port = 9000 #配置watch dog端口 wd_priority = 1 wd_authkey = '' wd_ipc_socket_dir = '/tmp' delegate_IP = '192.168.180.221' #配置 pgpool 的 VIP,避免 pgpool 的单点故障 if_cmd_path = '/sbin' #以下几个网卡命令不需要修改 if_up_cmd = 'ip addr add $_IP_$/24 dev eth0 label eth0:0' if_down_cmd = 'ip addr del $_IP_$/24 dev eth0' arping_path = '/usr/sbin' arping_cmd = 'arping -U $_IP_$ -w 1' clear_memqcache_on_escalation = on wd_escalation_command = '' wd_de_escalation_command = '' wd_monitoring_interfaces_list = '' wd_lifecheck_method = 'heartbeat' wd_interval = 10 wd_heartbeat_port = 9694 wd_heartbeat_keepalive = 2 wd_heartbeat_deadtime = 30 heartbeat_destination0 = '192.168.180.223' #配置对端的 hostname heartbeat_destination_port0 = 9694 #配置对端的 hostname heartbeat_device0 = 'eth0' #配置对端的 hostname wd_life_point = 3 wd_lifecheck_query = 'SELECT 1' wd_lifecheck_dbname = 'postgres' wd_lifecheck_user = 'postgres' wd_lifecheck_password = 'postgres' other_pgpool_hostname0 = '192.168.180.223' #配置对端的 pgpool other_pgpool_port0 = 9999 #配置对端的 pgpool other_wd_port0 = 9000 #配置对端的 pgpool-wacthdog relcache_expire = 0 relcache_size = 256 check_temp_table = on check_unlogged_table = on memory_cache_enabled = off memqcache_method = 'shmem' memqcache_memcached_host = 'localhost' memqcache_memcached_port = 11211 memqcache_total_size = 67108864 memqcache_max_num_cache = 1000000 memqcache_expire = 0 memqcache_auto_cache_invalidation = on memqcache_maxcache = 409600 memqcache_cache_block_size = 1048576 memqcache_oiddir = '/var/log/pgpool/oiddir' white_memqcache_table_list = '' black_memqcache_table_list = ''
四、slave pgpool.conf的配置
listen_addresses = '*' port = 9999 socket_dir = '/var/run/postgresql' listen_backlog_multiplier = 2 serialize_accept = off pcp_listen_addresses = '*' pcp_port = 9898 pcp_socket_dir = '/var/run/postgresql' backend_hostname0 = '192.168.180.222' backend_port0 = 5432 backend_weight0 = 1 backend_data_directory0 = '/var/lib/postgresql/9.5/main' backend_flag0 = 'ALLOW_TO_FAILOVER' backend_hostname1 = '192.168.180.223' backend_port1 = 5432 backend_weight1 = 1 backend_data_directory1 = '/var/lib/postgresql/9.5/main' backend_flag1 = 'ALLOW_TO_FAILOVER' enable_pool_hba = on pool_passwd = 'pool_passwd' authentication_timeout = 60 ssl = off num_init_children = 32 max_pool = 4 child_life_time = 300 child_max_connections = 0 connection_life_time = 450 client_idle_limit = 300 log_destination = 'syslog' log_line_prefix = '%t: pid %p: ' log_connections = off log_hostname = off log_statement = off log_per_node_statement = off log_standby_delay = 'none' syslog_facility = 'LOCAL0' syslog_ident = 'pgpool' debug_level = 0 pid_file_name = '/var/run/pgpool/pgpool.pid' logdir = '/tmp' connection_cache = on reset_query_list = 'ABORT; DISCARD ALL' replication_mode = off replicate_select = off insert_lock = off lobj_lock_table = '' replication_stop_on_mismatch = off failover_if_affected_tuples_mismatch = off load_balance_mode = on ignore_leading_white_space = on white_function_list = '' black_function_list = 'currval,lastval,nextval,setval' database_redirect_preference_list = '' app_name_redirect_preference_list = '' allow_sql_comments = off master_slave_mode = on master_slave_sub_mode = 'stream' sr_check_period = 5 sr_check_user = 'postgres' sr_check_password = 'postgres' sr_check_database = 'postgres' delay_threshold = 0 follow_master_command = '' health_check_period = 1 health_check_timeout = 10 health_check_user = 'postgres' health_check_password = 'postgres' health_check_database = 'postgres' health_check_max_retries = 1 health_check_retry_delay = 2 connect_timeout = 10000 failover_command = '/usr/lib/postgresql/9.5/bin/failover_stream.sh %d %H /tmp/trigger_file0' failback_command = '' fail_over_on_backend_error = on search_primary_node_timeout = 10 recovery_user = 'postgres' recovery_password = 'postgres' recovery_1st_stage_command = '' recovery_2nd_stage_command = '' recovery_timeout = 90 client_idle_limit_in_recovery = 0 use_watchdog = on trusted_servers = '' ping_path = '/bin' wd_hostname = '192.168.180.223' wd_port = 9000 wd_priority = 1 wd_authkey = '' wd_ipc_socket_dir = '/tmp' delegate_IP = '192.168.180.221' if_cmd_path = '/sbin' if_up_cmd = 'ip addr add $_IP_$/24 dev eth0 label eth0:0' if_down_cmd = 'ip addr del $_IP_$/24 dev eth0' arping_path = '/usr/sbin' arping_cmd = 'arping -U $_IP_$ -w 1' clear_memqcache_on_escalation = on wd_escalation_command = '' wd_de_escalation_command = '' wd_monitoring_interfaces_list = '' wd_lifecheck_method = 'heartbeat' wd_interval = 10 wd_heartbeat_port = 9694 wd_heartbeat_keepalive = 2 wd_heartbeat_deadtime = 30 heartbeat_destination0 = '192.168.180.222' heartbeat_destination_port0 = 9694 heartbeat_device0 = 'eth0' wd_life_point = 3 wd_lifecheck_query = 'SELECT 1' wd_lifecheck_dbname = 'postgres' wd_lifecheck_user = 'postgres' wd_lifecheck_password = 'postgres' other_pgpool_hostname0 = '192.168.180.222' other_pgpool_port0 = 9999 other_wd_port0 = 9000 relcache_expire = 0 relcache_size = 256 check_temp_table = on check_unlogged_table = on memory_cache_enabled = off memqcache_method = 'shmem' memqcache_memcached_host = 'localhost' memqcache_memcached_port = 11211 memqcache_total_size = 67108864 memqcache_max_num_cache = 1000000 memqcache_expire = 0 memqcache_auto_cache_invalidation = on memqcache_maxcache = 409600 memqcache_cache_block_size = 1048576 memqcache_oiddir = '/var/log/pgpool/oiddir' white_memqcache_table_list = '' black_memqcache_table_list = '
五、两边都放好/usr/lib/postgresql/9.5/bin/failover_stream.sh数据库连接出问题后的脚本,给到postgres用户755权限
#! /bin/sh # Failover command for streaming replication. # This script assumes that DB node 0 is primary, and 1 is standby. # # If standby goes down, do nothing. If primary goes down, create a # trigger file so that standby takes over primary node. # # Arguments: $1: failed node id. $2: new master hostname. $3: path to # trigger file. failed_node=$1 new_master=$2 trigger_file=$3 # Do nothing if standby goes down. if [ $failed_node = 1 ]; then exit 0; fi # Create the trigger file. /usr/bin/ssh -T $new_master /bin/touch $trigger_file exit 0;
六、启动前的准备
1、两边都新建配置文件中的目录
mkdir /var/run/pgpool #加入到/etc/rc.local,貌似这玩意儿新建以后会自动删掉还不自动建。。。 mkdir /var/run/postgresql#加入到/etc/rc.local mkdir /var/log/pgpool
2、两边都copy个pgpool.conf出来
加入如下内容,否则会出现错误“psql: RROR: MD5 authentication is unsupported in replication, master-slave and parallel modes.HINT: check pg_hba.conf”
host all all 0.0.0.0/0 md5
3、pool_passwd中设置用户名密码验证
/usr/local/pgpool/bin/pg_md5 -m -p -u postgres pool_passwd
4、新建一个脚本专门用于停止pgpool的主服务的,当然也可以用作备机
vim /usr/local/etc/rm_pgpool.sh ps -ef | grep pgpool | cut -c 9-15 | xargs kill -9 ps -ef | grep arping | cut -c 9-15 | xargs kill -9 rm -rf /var/run/postgresql/.s.PGSQL.5432 rm -rf /tmp/.s.PGPOOLWD_CMD.9000 /tmp/.s.PGSQL.9898 ip addr del 192.168.180.221/24 dev eth0 label eth0:0
5、pgpool的自启动
vim /etc/rc.local /usr/local/etc/rm_pgpool.sh pgpool -f /usr/local/etc/pgpool.conf -F /usr/local/etc/pcp.conf -a /usr/local/etc/pool_hba.conf -D
七、测试
1、PG的主备切换
原理和我另外一篇PG流复制主备的一样,PGPOOL主要就是检测到比如主机PG挂掉了,调用failer_command在最新的主机即备机上创建一个文件从而激活备机。当然PGPOOL的VIP不会跟着漂移,这个可以在PG切换完成后再去切换
先打开主备机的pgpool\pg日志观察,防止某些错误没有看到导致切换出错
master:/etc/init.d/postgresql stop
slave:$PGDATA/recovery.conf变为recovery.done
slave:pg_controldata | grep cluster,显示为in production
slave:psql->show transaction_read_only,显示为off
slave:ifconfig,显示VIP在线
vip:show pool_nodes,显示原master主机状态为3且为standby、原slave备机状态为2且为primary
如果要原主机恢复为standby,则得把/tmp/trigger_file0删掉,重命名recovery.done为recovery.conf,然后再启动原主机
2、PGPOOL的主备切换
pgpool VIP :192.168.180.221 从 master飘到 slave,注意此时仅 pgpool 的 VIP 飘移, master,slave上的数据库角色不变(或者说是PG的主备关系不变), pgpool 的切换非常容易
关闭 pgpool :
pgpool -m fast stop
启动pgpool并清除状态:
pgpool -f /usr/local/etc/pgpool.conf -F /usr/local/etc/pcp.conf -a /usr/local/etc/pool_hba.conf -D
八、后期操作
1、查看当前主备状态
使用pgpool登陆:show pool_nodes ;
0 192.168.180.222 5433 2 0.500000 primary 83
1 192.168.180.223 5433 2 0.500000 standby 0
2、如果当主节点挂掉再恢复为standby后,pool_nodes的status仍然为3,这时候就得两边pgpool都重启下,一般先重启pgpool的备机再重启主机即可,记住重启的时候肯定要一直Ping VIP,一定要在同一网段的其他机器上ping,非同一网段可能会被arp误导
九、错误
有时候关闭备机了,但是主机连pgpool -m fast stop都无法关闭,只能ps -ef | grep pgpool kill掉相关进程,还要netstat -anp | grep arping再kill掉这个进程,然后再去/var/run/postgresql和/tmp目录找到.s*打头的隐藏文件除了postgresql自己端口的基本上都是pgpool的删掉,否则启动报错。。。