暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PostgreSQL 12.2 高可用集群搭建

云原生转型实验室 2020-06-04
1287

本文记录了如何在RHEL 7.6下搭建PostgreSQL 12.2的一主两备高可用集群。


一、方案比较


官网共列了8种方案,各有优缺点,详细可参考:

https://www.postgresql.org/docs/current/different-replication-solutions.html

 图1.高可用方案比较


综合比较后,本文将选用流复制的同步方式搭建一主两备的高可用集群,主要优势有:主备强一致性、数据永不丢失、原生备份方式、轻量、读性能佳;主要缺点为只能主机执行写,且同步模式下需等待备机写完。因此,想要做读写分离,或者对于读性能要求高、写请求性能要求不那么高的场景,该方案是比较合适的。


流复制的主要原理


流复制是搭建主备库的一种有效方式,它不需要额外增加软件,只需要在单数据库模式的基础上,再复制一份PostgreSQL数据库到另外的一台机器上,对两台数据库进行参数配置,即可实现。

 

这两套数据库之间的数据,通过wal日志,后台自动同步。对外部的应用程序而言,可以看作是两套数据库,需要根据业务需要,显式分别连接不同的数据库。


PG主备流复制的核心部分由walsender,walreceiver和startup三个进程组成。

walsender进程是用来发送WAL日志记录的,执行顺序如下:

 

PostgresMain()->exec_replication_command()->StartReplication()->WalSndLoop()->XLogSendPhysical()

 

walreceiver进程是用来接收WAL日志记录的,执行顺序如下:

 

sigusr1_handler()->StartWalReceiver()->AuxiliaryProcessMain()->WalReceiverMain()->walrcv_receive()

 

startup进程是用来apply日志的,执行顺序如下:

 

PostmasterMain()->StartupDataBase()->AuxiliaryProcessMain()->StartupProcessMain()->StartupXLOG()

 

下图是PG主备总体框架图:

图2.PG主备总体框架图

 

walsender和walreceiver进程流复制过程

walsender和walreceiver交互主要分为以下几个步骤:

1、walreceiver启动后通过recovery.conf文件中的primary_conninfo参数信息连向主库,主库通过连接参数replication=true启动walsender进程;

2、walreceiver执行identify_system命令,获取主库systemid/timeline/xlogpos等信息,执行TIMELINE_HISTORY命令拉取history文件;

3、执行wal_startstreaming开始启动流复制,通过walrcv_receive获取WAL日志,期间也会回应主库发过来的心跳信息(接收位点、flush位点、apply位点),向主库发送feedback信息(最老的事务id),避免vacuum删掉备库正在使用的记录;

4、执行walrcv_endstreaming结束流复制,等待startup进程更新receiveStart和receiveStartTLI,一旦更新,重新进入2/3/4步骤。


二、环境准备


#准备3RHEL7.6的虚机


角色

IP

端口

数据库用户名/密码

流复制用户名/密码

主机名

主库

192.168.0.145

5432

postgres/postgres

repl/

postgres

pgmaster

备库

192.168.0.146

5432

postgres/postgres

repl/

postgres

pgslave01

备库

192.168.0.147

5432

postgres/postgres

repl/

postgres

pgslave02

 

#防火墙设置

firewall-cmd --zone=public --add-port=5432/tcp

 

#关闭selinux

sed -ri s/SELINUX=enforcing/SELINUX=disabled/g  etc/selinux/config

setenforce 0

 

# 配置阿里云yum

mv etc/yum.repos.d/CentOS-Base.repo  etc/yum.repos.d/CentOS-Base.repo.bak

curl -o etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo

 

#安装NTP

yum -y install ntpntpdate

systemctl enable ntpd

vi etc/ntp.conf

# 添加ntp服务器地址

server ntp1.aliyun.comprefer   

server ntp2.aliyun.com         

server ntp3.aliyun.com

service ntpd stop(关闭服务)

ntpdate ntp1.aliyun.com(手动更新一次)

sevice ntpd start(开启服务)

 

三、安装PostgreSQL


官方下载地址:

https://www.postgresql.org/download/

 

#Install the repositoryRPM:
yum install
https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm

 

#Install the clientpackages:
yum install postgresql12

 

#Optionally install theserver packages:
yum install postgresql12-server

 

#若要内网环境安装,可通过yum下载rpm

yum install postgresql12 postgresql12-server  --downloadonly--downloaddir=~/

 

#rpm安装顺序

1、postgresql12-libs-12.2-1PGDG.rhel7.x86_64

2、postgresql12-12.2-1PGDG.rhel7.x86_64               #客户端

3、postgresql12-server-12.2-1PGDG.rhel7.x86_64  #服务端

 

#rpm安装

rpm -ivhpostgresql12-libs-12.2-1PGDG.rhel7.x86_64

\postgresql12-12.2-1PGDG.rhel7.x86_64

\postgresql12-server-12.2-1PGDG.rhel7.x86_64

 

#初始化数据库

/usr/pgsql-12/bin/postgresql-12-setupinitdb 

systemctl enable postgresql-12                         
systemctl start postgresql-12

 

#修改postgreq用户的密码

passwd postgres

更改用户postgres 的密码。

新的密码:

无效的密码:密码是一个回文

重新输入新的密码:

passwd:所有的身份验证令牌已经成功更新。

 

su - postgres

-bash-4.2$ psql

psql (12.1)

输入"help" 来获取帮助信息.

 

postgres=# ALTER USERpostgres with password 'postgres';

ALTER ROLE

postgres=# \q

-bash-4.2$ exit

登出

 

 

#修改数据库访问权限

 vi/var/lib/pgsql/12/data/pg_hba.conf

......

# TYPE  DATABASE        USER            ADDRESS                 METHOD

 

# "local" is for Unixdomain socket connections only

local   all             all                                     md5

# IPv4 local connections:

host    all             all             127.0.0.1/32            md5

host    all              all             0.0.0.0/0               md5

# IPv6 local connections:

host    all             all             ::1/128                 md5

# Allow replication connections fromlocalhost, by a user with the

# replication privilege.

#local   replication     all                                     peer

#host    replication     all             127.0.0.1/32            ident

#host    replication     all             ::1/128                 ident

host    replication     repl            192.168.0.145/30        trust

 

#允许远程访问数据库

 vi var/lib/pgsql/12/data/postgresql.conf

# - Connection Settings-

 

listen_addresses ='*'                  # what IPaddress(es) to listen on;

                                        # comma-separated list of addresses;

                                        #defaults to 'localhost'; use '*' for all

                                        #(change requires restart)

port = 5432                             # (change requiresrestart)

 

#重启数据库

systemctl restart postgresql-12

 

#设置环境变量

cat  <<EOF >/etc/profile.d/pgsql.sh

POSTGRESQL12_HOME=/usr/pgsql-12

PATH=\$POSTGRESQL12_HOME/bin:\$PATH

export POSTGRESQL12_HOMEPATH

EOF

 

source etc/profile.d/pgsql.sh

 

四、高可用配置


1、主库设置


su - postgres

 

##初始化

initdb -D/data/pgdata/data -U postgres --locale=en_US.UTF8 -E UTF8

 

cp /data/pgdata/data/{pg_hba.conf,pg_hba.conf.bak}

 


## 允许repl用户进行流复制(这步前面已完成,不需要再单独配了)

cat  <<-eof>>/data/pgdata/data/pg_hba.conf

host    all             all             0.0.0.0/0               md5

host    replication     repl            192.168.0.145/30            trust

eof


cp /data/pgdata/data/{postgresql.conf,postgresql.conf.bak}

 

##配置postgresql.conf

cat  <<-eof>/data/pgdata/data/postgresql.conf

 

listen_addresses ='*'                    

port = 5432

max_connections = 100

superuser_reserved_connections= 10

unix_socket_directories= '/tmp'

 

shared_buffers = 512MB

temp_buffers = 16MB

work_mem = 32MB

maintenance_work_mem =128MB

#max_stack_depth = 2MB

dynamic_shared_memory_type= posix

 

wal_level = replica

full_page_writes = on

wal_log_hints = off             # also do full page writes ofnon-critical updates

                                               # (change requires restart)

wal_buffers = 16MB

wal_writer_delay = 200ms

commit_delay = 0

commit_siblings = 5

 

archive_mode = on

archive_command = 'test! -f /var/lib/pgsql/12/archivedir/%f && cp %p/var/lib/pgsql/12/archivedir/%f'

archive_timeout = 60s

 

max_wal_senders = 50

 

synchronous_standby_names = 'pgslave01, pgslave02'   #同步流复制的备机名字

 

hot_standby = on

 

effective_cache_size =2GB

 

log_destination ='csvlog'

logging_collector = on

log_directory = 'log'

log_filename ='postgresql-%Y-%m-%d_%H%M%S.log'

log_rotation_age = 1d

log_rotation_size = 10MB

log_statement = 'mod'

log_timezone ='Asia/Shanghai'     #PRC也行

 

timezone ='Asia/Shanghai'

 

eof

 

## 启动数据库

pg_ctl  start -D /var/lib/pgsql/12/data/ -l/var/lib/pgsql/12/data/serverlog

 

## 创建用户进行流复制连接

psql -U postgres -c"ALTER USER postgres WITH PASSWORD 'postgres';"

psql -U postgres -c"CREATE USER  repl WITH PASSWORD'postgres' REPLICATION;"

 

2、备库设置


以下以pgslave01为例,pgslave02同理。

 

su - postgres

 

pg_ctl stop -m fast -D /var/lib/pgsql/12/data/   #关闭数据库

sudo mv /var/lib/pgsql/12/data/*  /home/pgbak   #备份配置文件

 

## 进行一次主库数据基本备份到备库

pg_basebackup -h 192.168.0.145 -p 5432 -U repl -w -Fp -Xs -Pv -R -D /var/lib/pgsql/12/data/

 

pg_basebackup: 开始基础备份,等待检查点完成

pg_basebackup: 已完成检查点

pg_basebackup: 预写日志起始于时间点: 0/6000028, 基于时间轴1

pg_basebackup: 启动后台 WAL 接收进程

pg_basebackup: 已创建临时复制槽"pg_basebackup_15842"

33565/33565 kB (100%),1/1 表空间                                        

pg_basebackup: 预写日志结束点: 0/6000100

pg_basebackup: 等待后台进程结束流操作...

pg_basebackup: 同步数据到磁盘...

pg_basebackup: 基础备份已完成

 

 

##根据主库的postgresql.conf 配置文件修改参数配置:

 

listen_addresses = '* '

max_connections = 150, #一般比主库大一些.

 

wal_level =replica            

 

hot_standby = on

max_standby_streaming_delay= 30s    #默认

wal_receiver_status_interval= 10s        #默认

hot_standby_feedback =on # 如果有错误的数据复制,是否向主进行反应

 

primary_conninfo = 'application_name=pgslave01user=repl passfile=''/var/lib/pgsql/.pgpass'' host=192.168.0.145 port=5432sslmode=prefer sslcompression=0 gssencmode=prefer krbsrvname=postgrestarget_session_attrs=any'

 

## 启动备库

pg_ctl  start -D /var/lib/pgsql/12/data/ -l/var/lib/pgsql/12/data/serverlog

 

五、验证


##状态检查

### 回到主库查看状态

$ psql  -c "selectclient_addr,usename,backend_start,application_name,sync_state,sync_priorityFROM pg_stat_replication;"

 

  client_addr | usename |         backend_start         | application_name | sync_state |sync_priority

---------------+---------+-------------------------------+------------------+------------+---------------

192.168.0.147 | repl    | 2020-05-1016:47:23.051332+08 | pgslave02        | potential  |             2

 192.168.0.146 | repl    | 2020-05-10 16:45:46.412336+08 |pgslave01        | sync       |             1

(2 行记录)

 

$ psql  -c "select client_addr, sync_state frompg_stat_replication;"

  client_addr | sync_state

---------------+------------

192.168.0.147| potential

 192.168.0.146 | sync

(2 行记录)

 

##备库只读, 所以任何操作, 都会告警失败:

postgres=# drop databasetest;

错误不能在一个只读模式的事务中执行DROP DATABASE

 

## 查看主备的状态

#

ps -ef  |grep sender

postgres  38662  38651  16:47?       00:00:00 postgres: walsender repl192.168.0.146(42126) streaming 0/17000060

postgres  38677  38651  16:45?       00:00:00 postgres: walsender repl192.168.0.147(42290) streaming 0/17000060

postgres  38795 38606  0 17:16 pts/0    00:00:00 grep --color=auto sender 

 

#

ps -ef  |grep recover

postgres  16041 16039  0 16:45 ?        00:00:00 postgres: startup   recovering 000000010000000000000008

root      16112 14979  0 17:15 pts/0    00:00:00 grep --color=auto recover

 

#通过此命令判断主备

#

pg_controldata -D /var/lib/pgsql/12/data/

pg_control 版本:                      1201

Catalog 版本:                        201909212

数据库系统标识符:                     6822534294356894336

数据库簇状态:                         在运行中

 

#

pg_controldata -D/var/lib/pgsql/12/data/

pg_control 版本:                      1201

Catalog 版本:                        201909212

数据库系统标识符:                     6822534294356894336

数据库簇状态:                         正在归档恢复

 


文章转载自云原生转型实验室,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论