您现在的位置是:网站首页> 编程资料编程资料

Postgresql主从异步流复制方案的深入探究_PostgreSQL_

2023-05-27 460人已围观

简介 Postgresql主从异步流复制方案的深入探究_PostgreSQL_

前言

数据库的备份工作在日常生产中极为重要,如果你咨询一个DBA如何才能设计出高可用的数据备份与恢复方案,相信很多人都会从架构上给出很多容灾的意见。但归根到底,如果业务环节中数据库还牵涉到分布式环境,我认为一个好的方案需要达到三大要求:

  • 多副本
  • 持久化
  • 一致性

日常架构设计中,我们不仅要保证数据额的成功备份,还要保证备份的数据可以快速恢复。在众多备份恢复可靠性方案中 主从复制 技术,可以说是最常见的实现,本文主要是介绍postgresql主备数据库的异步流复制的环境搭建与主备切换的操作实践,除了能把一些基础的原理运用在日常的数据库运维中,也可以加深对Postgresql数据库的底层知识了解。

postgres在9.0之后引入了主从的流复制机制,所谓流复制,就是从服务器通过tcp流从主服务器中同步相应的数据。这样当主服务器数据丢失时从服务器中仍有备份。

与基于文件日志传送相比,流复制允许保持从服务器更新。 从服务器连接主服务器,其产生的流WAL记录到从服务器, 而不需要等待主服务器写完WAL文件。

PostgreSQL流复制默认是异步的。在主服务器上提交事务和从服务器上变化可见之间有一个小的延迟,这个延迟远小于基于文件日志传送,通常1秒能完成。如果主服务器突然崩溃,可能会有少量数据丢失。

同步复制必须等主服务器和从服务器都写完WAL后才能提交事务。这样在一定程度上会增加事务的响应时间。

下面的学习与实践主要针对PostgreSQL的异步流复制(本文没有涉及到同步复制、逻辑复制等,如果大家想了解其它的备份方案,可以阅读相关官方文档或其他资料介绍)。

异步流复制的中心思想是:主库上提交事务时不需要等待备库接收WAL日志流并写入到备库WAL日志文件时便返回成功,因此异步流复制的TPS会相对同步流复制要高,延迟更低。

环境准备

操作系统服务器IP节点名称角色
centos 7.2172.17.0.2pghost1主库
centos 7.2172.17.0.5pghost2备库

主要目录规范:

  • 数据目录: /data/pg10/pg_root
  • 表空间目录: /data/pg10/pg_tbs
  • 应用程序目录: /apps/svr/pgsql

要注意的是:编译安装Pg我们使用的是root账户,但是一般情况下,我们对数据库的部署操作等应该使用非root的pg超级管理员账户,所以需要我们预先创建相关用户和目录,并设置相关权限:

 $ groupadd postgres $ useradd postgres -g postgres $ passwd postgres $ mkdir -p /data/pg10/pg_root $ mkdir -p /data/pg10/tbs $ chown -R postgres:postgres /data/pg10

实验用的postgresql为10.0版本

pghost1 和 pghost2 分别下载该版本的源码安装包

 wget https://ftp.postgresql.org/pub/source/v10.0/postgresql-10.0.tar.gz

下载后进行解压

 tar -zxvf postgresql-10.0.tar.gz

安装前依赖

由于 configure过程中依赖操作系统包zlib、readline等,所以我实用yum预先安装:

 yum groupinstall "Development tools” yum install -y bison flex readline readline-devel zlib zlib-devel

主备库数据库安装

安装前,我们先分别对pghost1 和 pghost2创建postgresql的偏好环境变量

 vi /etc/profile.d/pgsql.sh

追加以下内容:

 export PGPORT=1921 export PGUSER=postgres export PGDATA=/data/pg10/pg_root export LANG=en_US.utf8 export PGHOME=/apps/svr/pgsql export LD_LIBRARY_PATH=$PGHOME/lib:/lib64:/usr/lib64:/usr/local/lib64:/lib:/usr/lib:/usr/local/lib export PATH=$PGHOME/bin:$PATH:. export MANPATH=$PGHOME/share/man:$MANPATH alias rm='rm -i' alias ll='ls -lh'

保存文件,并让环境变量生效:

 source /etc/profile.d/pgsql.sh

再进入刚刚解压的 postgresql-10.0 目录中,执行以下命令:

 ./configure —prefix=/apps/svr/pgsql_10.0/ --with-pgport=1921

之后进行编译安装:

 gmake gmake install

安装完成后,我们可以使用以下命令确认是否安装成功:

 $ postgres --version postgres (PostgreSQL) 10.0

复制功能部署

在启动数据库服务搭建主从结构前,有几个比较重要的配置文件需要我们额外地进行创建与设置的,它们分别是:

  • postgreql.conf
  • pg_hba.conf
  • recovery.conf
  • .pgpass

下面我们会在实践中,具体地对上述的文件的配置进行相关说明

上一节,我们编译安装好了postgresql,我们接下来切换操作用户

 su postgresql

然后使用initdb工具初始化数据库:

 echo "123456" >> /data/pg10/pgpass initdb -D /data/pg10/pg_root -E UTF8 --locale=C -U postgres --pwfile=/data/pg10/pgpass

执行上述命令后,在/data/pg10/pg_root目录下会产生系统数据文件,

 PG_VERSION pg_dynshmem pg_multixact pg_snapshots pg_tblspc postgresql.auto.conf base pg_hba.conf pg_notify pg_stat pg_twophase postgresql.conf global pg_ident.conf pg_replslot pg_stat_tmp pg_wal pg_commit_ts pg_logical pg_serial pg_subtrans pg_xact

之后我们开始配置 /data/pg10/pg_root/postgresql.conf,修改以下几个关键项:

 listen_addresses = '*' wal_level = replica archive_mode = on archive_command = '/bin/date' max_wal_senders = 10 wal_keep_segments = 512 hot_standby = on

注:主库和备库的 /data/pg10/pg_root/postgresql.conf 配置建议完全一致

接下来我们在 备库 上配置 /data/pg10/pg_root/pg_hba.conf

 host replication repuser 172.17.0.2/32 md5 host replication repuser 172.17.0.5/32 md5

其实最好主库也配置一份,因为主库和备库的角色不是静止的,在手动或库出现故障情况下,它们的角色会互相更换。

之后,我们先启动主库 pghost1了 (记得切换到postgres用户):

 $ pg_ctl start -D $PGDATA ... ... database system is ready to accept connections done server started

使用PostgreSQL的超级管理员postgres登录到创建流复制用户repuser,流复制用户需要有 REPLICATION权限和LOGIN权限

 $ psql -U postgres -p 1921 psql (10.0) Type "help" for help. postgres=# CREATE USER repuser REPLICATION LOGIN CONNECTION LIMIT 5 ENCRYPTED PASSWORD 'domac123'; CREATE ROLE

以上命令基本完成主库上的配置,接下来我们需要热备生成一个备库,制作备库过程中主库仍然可以读写,不影响业务,我们在主库上创建备份任务:

 postgres=# select pg_start_backup('domacli_bak'); pg_start_backup ----------------- 0/2000060 (1 row)

pg_start_backup() 函数会在主库上发起一个在线备份,命令执行后,将数据文件压缩拷贝到备份节点上:

 $ tar czvf pg_root.tar.gz pg_root --exclude=pg_root/pg_wal $ scp pg_root.tar.gz postgres@172.17.0.5:/data/pg10

pg_wal目录不是必须复制的,可以排除这个目录,以节省空间,然后我们回到备库的/data/pg10下,执行主库备份文件的解压:

 $ tar xvf pg_root.tar.gz

解压后,我们回到主节点,执行停止备份命令,结束这次备份流程

 postgres=# select pg_stop_backup(); NOTICE: pg_stop_backup complete, all required WAL segments have been archived pg_stop_backup ---------------- 0/2000168 (1 row)

以上的命令表示完成在线备份,但备库上扔需要做一些配置,我们回到备库上,配置 /data/pg10/pg_root/recovery.conf文件,如果该文件不存在,可以执行以下命令,在软件目录中复制一个:

 cp $PGHOME/share/recovery.conf.sample /data/pg10/pg_root/recovery.conf

备库的 recovery.conf 配置以下参数

 recovery_target_timeline = 'latest' standby_mode = on primary_conninfo = 'host=172.17.0.2 port=1921 user=repuser'

主要观察recovery.conf中的参数primary_conninfo 中的 user=repuser, 还记得我们前面在主库上创建的流传输用户repuser吗?由于主备直接数据同步需要在用户下执行操作,而主库上我们创建repuser的时候,为了安全我设置了密码, 但recovery.conf我们没有配置明文密码,那么程序的密码如何获得呢?

我们建议把密码设置在 ~/.pgpass中:

你也可以直接在上面的recovery.conf 设置 primary_conninfo = ‘host=172.17.0.2 port=1921 user=repuser password=domac123', 但这样会有安全风险

 $ cd ~ $ touch .pgpass $ chmod 0600 .pgpass

填写以下内容:

 172.17.0.2:1921:replication:repuser:domac123 172.17.0.5:1921:replication:repuser:domac123

好了,当这些备注都就绪之后,我们可以开始启动我们的备库了:

 $ pg_ctl start ... database system is ready to accept read only connections done server started

如果备库正常启动,我们可以在主备两库上观察WAL发生与接收进程是否都同时工作,以确认异步流工作是否正常工作

主库上:

 ps -ef | grep wal postgres 6939 6935 0 23:16 ? 00:00:00 postgres: wal writer process postgres 6983 6935 0 23:42 ? 00:00:00 postgres: wal sender process repuser 172.17.0.5(45910) streaming 0/3000140

备库上:

 ps -ef | grep wal postgres 26481 26479 0 23:42 ? 00:00:00 postgres: wal receiver process streaming 0/3000140 postgres 26486 26448 0 23:42 ? 00:00:00 grep --color=auto wal

使用 pg_basebackup 方式部署流复制

接下来,介绍一种操作相对简洁的方式,上述我们配置操作所牵涉到的主要步骤有:

  • pg_start_backup
  • 两台服务器之间的数据拷贝
  • pg_stop_backup

以上三个步骤可以合成一步完成,PostgreSQL提供内置的pg_basebackup命令行工具支持对主库发起一个在线基准备份,并自动进入备份模式进行数据库基准备份,备份完成后自动从备份模式退出,不需要执行额外的pg_start_backup 和pg_stop_backup 命令显式地声明进入备份模式和退出备份模式,pg_basebackup工具是对数据库实例级进行的物理备份,因此这个工具通常作为备份工具对据库进行基准备份

pg_basebackup工具发起备份需要超级用户权限或REPLICATION权限,注意max_wal_senders参数配置,因为pg_basebackup工具将消耗至少一个WAL发送进程。本节将演示通过pg_basebackup工具部署异步流复制,之前已经在pghost2上部署了一个备库,我们先将这个备库删除,之后通过pg_basebackup工具重新做一次备库,删除pghost2上的备库只需要先停备库之后删除备库数据库数据文件即可,如下所示:

进入pghost2服务器上(172.17.0.5)

 $ pg_ctl stop -m fast waiting for server to shut down.... done server stopped $ rm -rf $PGDATA $ rm -rf /data/pg10/pg_tbs

接下来,在pghost2上,使用pg_basebackup触发基准备份

 pg_basebackup -D $PGDATA -Fp -Xs -v -P -h 172.17.0.2 -p 1921 -U repuser -W

执行后,会看到相关的日志输出

 pg_basebackup: initiating base backup, waiting for checkpoint to complete pg_basebackup: checkpoint completed pg_basebackup: write-ahead log start point: 0/20007A8 on timeline 1 pg_basebackup: starting background WAL receiver 22655/22655 kB (100%), 1/1 tablespace pg_basebackup: write-ahead log end point: 0/2000888 pg_basebackup: waiting for background process to finish streaming ... pg_basebackup: base backup completed

从以上日志信息看出pg_basebackup命令首先对数据库做一次checkpoint,之后基于时间点做一个全库基准备份,全备过程中会拷贝$PGDATA数据文件和表空间文件到备库节点对应目录

最后,跟之前使用pg_start_backup的方式一样,备库记得配置recovery.conf

 recovery_target_timeline = 'latest' standby_mode = on prim
                
                

-六神源码网