天天看点

postgresql主从实现之异步流复制查看复制状态

postgresql主从复制实现方式之一:

基于Standby的异步流复制,这是PostgreSQL9.x版本(2010.9)之后提供的一个很nice的功能,类似的功能在Oracle中是11g之后才提供的active dataguard和SQL Server 2012版本之后才提供的日志传送,此处再次为pg鼓掌,确实是一个很棒的开源数据库。废话不多说,本篇blog就详细记录一下在pg9.5中实现Hot Standby异步流复制的完整配置过程和注意事项。

Standby数据库原理:

首先我们做主从同步的目的就是实现db服务的高可用性,通常是一台主数据库提供读写,然后把数据同步到另一台从库,然后从库不断apply从主库接收到的数据,从库不提供写服务,只提供读服务。在postgresql中提供读写全功能的服务器称为primary database或master database,在接收主库同步数据的同时又能提供读服务的从库服务器称为hot standby server。

PostgreSQL在数据目录下的pg_xlog子目录中维护了一个WAL日志文件,该文件用于记录数据库文件的每次改变,这种日志文件机制提供了一种数据库热备份的方案,即:在把数据库使用文件系统的方式备份出来的同时也把相应的WAL日志进行备份,即使备份出来的数据块不一致,也可以重放WAL日志把备份的内容推到一致状态。这也就是基于时间点的备份(Point-in-Time Recovery),简称PITR。而把WAL日志传送到另一台服务器有两种方式,分别是:

    WAL日志归档(base-file)

    流复制(streaming replication)

第一种是写完一个WAL日志后,才把WAL日志文件拷贝到standby数据库中,简言之就是通过cp命令实现远程备份,这样通常备库会落后主库一个WAL日志文件。而第二种流复制是postgresql9.x之后才提供的新的传递WAL日志的方法,它的好处是只要master库一产生日志,就会马上传递到standby库,同第一种相比有更低的同步延迟,所以我们肯定也会选择流复制的方法。

在实际操作之前还有一点需要说明就是standby的搭建中最关键的一步——在standby中生成master的基础备份。postgresql9.1之后提供了一个很方便的工具—— pg_basebackup,关于它的详细介绍和参数说明可以在官网中查看(pg_basebackup tool).下面在搭建过程中再做相关具体说明,关于一些基础概念和原理先介绍到这里。

pg_basebackup tool官网介绍:

https://www.postgresql.org/docs/current/static/p-pgbasebackup.html

详细配置环境:

下面开始实战,首先准备两台服务器,我这里开了2个虚机做测试,分别是:

主库(master)CentOS release 6.5 (Final) 10.0.0.100 postgresql 9.5.9

从库(standby)CentOS release 6.7 (Final) 10.0.0.110 postgresql 9.5.9

从主库配置开始。

首先要提前在master机器10.0.0.100安装好postgresql,采用的是二进制安装包,具体参考本博文的postgresql二进制安装过程。

主库配置:

注意此处的操作都是在主库(10.0.0.100)上进行的,首先打开数据目录下的postgresql.conf文件然后做以下修改:

1.listen_address = ‘*’(默认localhost)

2.port = 10280       (默认是5432)

3.wal_level = hot_standby(默认是minimal)

4.max_wal_senders=2(默认是0)

5.wal_keep_segments=64(默认是0)

下面对上述参数稍作说明

第一个是监听任何主机,wal_level表示启动搭建Hot Standby,max_wal_senders则需要设置为一个大于0的数,它表示主库最多可以有多少个并发的standby数据库,而最后一个wal_keep_segments也应当设置为一个尽量大的值,以防止主库生成WAL日志太快,日志还没有来得及传送到standby就被覆盖,但是需要考虑磁盘空间允许,一个WAL日志文件的大小是16M:

[postgres@localhost data]$ cd /data/pgsql100/data/pg_xlog/

[postgres@localhost pg_xlog]$ ls

000000010000000000000001  000000010000000000000002  000000010000000000000003  000000010000000000000004  000000010000000000000005  archive_status

[postgres@localhost pg_xlog]$ du -sh *

16M    000000010000000000000001

16M    000000010000000000000002

16M    000000010000000000000003

16M    000000010000000000000004

16M    000000010000000000000005

4.0K    archive_status

如上,一个WAL日志文件是16M,如果wal_keep_segments设置为64,也就是说将为standby库保留64个WAL日志文件,那么就会占用16*64=1GB的磁盘空间,所以需要综合考虑,在磁盘空间允许的情况下设置大一些,就会减少standby重新搭建的风险。接下来还需要在主库创建一个超级用户来专门负责让standby连接去拖WAL日志:

CREATE ROLE replica login replication encrypted password 'replica';

接下来打开数据目录下的pg_hba.conf文件然后做以下修改:

[postgres@localhost pg_xlog]$ tail -2 /data/pgsql100/data/pg_hba.conf 

#host    replication     postgres        ::1/128                 trust

host    replication     replica     10.0.0.110/32                md5

如上,这行配置的意思是允许用户replica从10.0.0.110/32网络上发起到本数据库的流复制连接,简言之即允许从库服务器连接主库去拖WAL日志数据。主库配置很简单,到此就算结束了,启动主库并继续配置从库

pg_ctl -D /data/pgsql100/data -l /data/pgsql100/log/postgres.log stop

pg_ctl -D /data/pgsql100/data -l /data/pgsql100/log/postgres.log start

从库配置:

首先要说明的是从库上一开始也是需要安装postgresql数据库服务的,应为需要pg_basebackup命令工具才能在从库上生成的master主库的基础备份。但是还要强调一点的是:从库上初始化数据库时指定的数据目录/data/psql110/data需要清空,才可以在从库上使用pg_basebackup命令工具来生成master主库的基础备份数据。

从此处开始配置从库(10.0.0.110),首先要通过pg_basebackup命令行工具在从库上生成基础备份:

[postgres@localhost data]$ pg_basebackup -h 10.0.0.100 -U replica -p 10280 -F p -x -P -R -D /data/psql110/data/ -l replbackup

Password: 密码(replica)

46256/46256 kB (100%), 1/1 tablespace

[postgres@localhost data]$ 

简单做一下参数说明(可以通过pg_basebackup --help进行查看),

-h指定连接的数据库的主机名或IP地址,这里就是主库的ip。

-U指定连接的用户名,此处是我们刚才创建的专门负责流复制的repl用户。

-F指定了输出的格式,支持p(原样输出)或者t(tar格式输出)。

-x表示备份开始后,启动另一个流复制连接从主库接收WAL日志。

-P表示允许在备份过程中实时的打印备份的进度。

-R表示会在备份结束后自动生成recovery.conf文件,这样也就避免了手动创建。

-D指定把备份写到哪个目录,这里尤其要注意一点就是做基础备份之前从库的数据目录(/data/psql110/data/)目录需要手动清空。

-l表示指定一个备份的标识。

[postgres@localhost data]$ cat /data/psql110/data/recovery.conf 

standby_mode = 'on'

primary_conninfo = 'user=replica password=replica host=10.0.0.100 port=10280 sslmode=prefer sslcompression=1 krbsrvname=postgres'

运行命令后看到如下进度提示就说明生成基础备份成功: 

如上由于我们在pg_hba.conf中指定的md5认证方式,所以需要输入密码。最后还需要修改一下从库数据目录下的postgresql.conf文件,将hot_standby改为启用状态,即hot_standby=on。到此为止就算配置结束了,我们现在可以启动从库,

[postgres@localhost data]$ egrep -v '^#|^$' /data/psql110/data/postgresql.conf|grep "hot_standby"

wal_level = hot_standby            # minimal, archive, hot_standby, or logical

hot_standby = on            # "on" allows queries during recovery

[postgres@localhost data]$ pg_ctl -D /data/psql110/data -l /data/psql110/log/postgres.log start

server starting

从库上查看到流复制进程:

[postgres@localhost data]$ ss -lntup|grep postgres

tcp    LISTEN     0      128                   :::10280                :::*      users:(("postgres",23161,4))

tcp    LISTEN     0      128                    *:10280                 *:*      users:(("postgres",23161,3))

[postgres@localhost data]$ ps -ef|grep postgres

root       5663   4716  0 18:12 pts/0    00:00:00 su - postgres

postgres   5664   5663  0 18:12 pts/0    00:00:00 -bash

postgres   5855   5664  0 18:13 pts/0    00:00:00 /bin/bash /usr/local/pgsql/bin/psql

postgres   5857   5855  0 18:13 pts/0    00:00:00 /usr/local/pgsql/bin/psql.bin

root      12406   7244  0 18:34 pts/1    00:00:00 su - postgres

postgres  12407  12406  0 18:34 pts/1    00:00:00 -bash

root      13861  13810  0 18:47 pts/3    00:00:00 su - postgres

postgres  13862  13861  0 18:47 pts/3    00:00:00 -bash

root      21768  21736  0 19:54 pts/2    00:00:00 su - postgres

postgres  21769  21768  0 19:54 pts/2    00:00:00 -bash

postgres  23161      1  0 20:05 pts/2    00:00:00 /usr/local/pgsql/bin/postgres -D /data/psql110/data

postgres  23164  23161  0 20:05 ?        00:00:00 postgres: startup process   recovering 000000010000000000000007

postgres  23165  23161  0 20:05 ?        00:00:00 postgres: checkpointer process                     

postgres  23166  23161  0 20:05 ?        00:00:00 postgres: writer process                           

postgres  23167  23161  0 20:05 ?        00:00:00 postgres: stats collector process                  

postgres  23168  23161  0 20:05 ?        00:00:00 postgres: wal receiver process   streaming 0/7000140

postgres  23240  21769  0 20:06 pts/2    00:00:00 ps -ef

postgres  23241  21769  0 20:06 pts/2    00:00:00 grep postgres

主库上查看到流复制进程:

[postgres@localhost pg_xlog]$ ps -ef|grep postgres

root       2904   2642  0 00:40 pts/0    00:00:00 su - postgres

postgres   2905   2904  0 00:40 pts/0    00:00:00 -bash

postgres   2939      1  0 00:42 pts/0    00:00:00 /usr/local/pgsql/bin/postgres -D /data/pgsql100/data

postgres   2941   2939  0 00:42 ?        00:00:00 postgres: checkpointer process                      

postgres   2942   2939  0 00:42 ?        00:00:00 postgres: writer process                            

postgres   2943   2939  0 00:42 ?        00:00:00 postgres: wal writer process                        

postgres   2944   2939  0 00:42 ?        00:00:00 postgres: autovacuum launcher process               

postgres   2945   2939  0 00:42 ?        00:00:00 postgres: stats collector process                   

root       3109   3064  0 00:58 pts/2    00:00:00 su - postgres

postgres   3110   3109  0 00:58 pts/2    00:00:00 -bash

postgres   3151   3110  0 00:59 pts/2    00:00:00 /bin/bash /usr/local/pgsql/bin/psql -p10280

postgres   3153   3151  0 00:59 pts/2    00:00:00 /usr/local/pgsql/bin/psql.bin -p10280

root       3189   3087  0 01:07 pts/3    00:00:00 su - postgres

postgres   3190   3189  0 01:07 pts/3    00:00:00 -bash

postgres   3272   2939  0 01:25 ?        00:00:00 postgres: postgres testdb01 [local] idle            

postgres   3415   2939  0 02:16 ?        00:00:00 postgres: wal sender process replica 10.0.0.110(34021) streaming 0/7000140

postgres   3422   3190  0 02:17 pts/3    00:00:00 ps -ef

postgres   3423   3190  0 02:17 pts/3    00:00:00 grep postgres

此时从库上可以看到流复制的进程,同样的主库也能看到该进程。表明主从流复制配置成功。

同步测试演示:

创建库和建表做测试,在master服务器(10.0.0.100)中的创建testdb02库并且建一张表并添加几条数据:

master上操作:

postgres=# create database testdb02;

CREATE DATABASE

检查:

[postgres@localhost pg_xlog]$ psql -p10280 -c '\list'|grep testdb02

 testdb02  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 

testdb01=# \c testdb02

You are now connected to database "testdb02" as user "postgres".

testdb02=# \d

No relations found.

创建表:

CREATE TABLE weather ( city varchar(80), temp_lo int, temp_hi int, prcp real,date date);

          List of relations

 Schema |  Name   | Type  |  Owner   

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

 public | weather | table | postgres

(1 row)

testdb02=# \d weather

           Table "public.weather"

 Column  |         Type          | Modifiers 

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

 city    | character varying(80) | 

 temp_lo | integer               | 

 temp_hi | integer               | 

 prcp    | real                  | 

 date    | date                  | 

testdb02=# 

testdb02=# INSERT INTO weather (city, temp_lo, temp_hi, prcp, date) VALUES ('China05', '47', '59', '1.0', '1994-12-15');

INSERT 0 1

testdb02=# INSERT INTO weather (city, temp_lo, temp_hi, prcp, date) VALUES ('China04', '46', '58', '2.0', '1994-12-14');\

testdb02=# select * from weather;

  city   | temp_lo | temp_hi | prcp |    date    

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

 China05 |      47 |      59 |    1 | 1994-12-15

 China04 |      46 |      58 |    2 | 1994-12-14

(2 rows)

从库上检查:

[postgres@localhost data]$  psql -p10280 -c '\list'|grep testdb02

postgres=# \c testdb02;

testdb02=# \d weather;

testdb02=#

可以看到完美同步,那么从库是否能删除呢?测试一下:

从库上测试删除数据库testdb02;

postgres=# drop database testdb02;

ERROR:  cannot execute DROP DATABASE in a read-only transaction

postgres=# drop database testdb01;

standby的数据无法删除,正如我们之前说的,standby只提供只读服务,而只有master才能进行读写操作,所以master才有权限删除数据。master删除的同时standby中的数据也将同步删除,

主库中执行

<a href="https://s4.51cto.com/oss/201710/29/7cdecd8be51e6a025b4afd68ea3b68ed.png-wh_500x0-wm_3-wmp_4-s_675295564.png" target="_blank"></a>

关于异步流复制的内容到这里.

参考博文:

http://blog.csdn.net/wzyzzu/article/details/53331206

 本文转自 wjw555 51CTO博客,原文链接:http://blog.51cto.com/wujianwei/1977210