postgresql主从实现之异步流复制

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
简介:

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'


运行命令后看到如下进度提示就说明生成基础备份成功: 
[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_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);
testdb02=# \d
          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');\
INSERT 0 1
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)
testdb02=# 

从库上检查:
[postgres@localhost data]$  psql -p10280 -c '\list'|grep testdb02
 testdb02  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 

postgres=# \c testdb02;
You are now connected to database "testdb02" as user "postgres".
testdb02=# \d
          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=# 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)

testdb02=#
可以看到完美同步,那么从库是否能删除呢?测试一下:
从库上测试删除数据库testdb02;
postgres=# drop database testdb02;
ERROR:  cannot execute DROP DATABASE in a read-only transaction
postgres=# drop database testdb01;
ERROR:  cannot execute DROP DATABASE in a read-only transaction

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

查看复制状态

主库中执行

7cdecd8be51e6a025b4afd68ea3b68ed.png-wh_

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

参考博文:

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


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


相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
7月前
|
弹性计算 关系型数据库 数据库
搭建PostgreSQL主从架构
PostgreSQL是一个关系型数据库管理系统(RDBMS),支持NoSQL数据类型(JSON/XML/hstore)。本教程介绍如何在两台CentOS 7操作系统的ECS实例上搭建PostgreSQL主从架构。
151 0
|
8月前
|
SQL XML 弹性计算
【ECS生长万物之开源】搭建PostgreSQL主从架构
PostgreSQL被业界誉为最先进的开源数据库,支持NoSQL数据类型(JSON/XML/hstore)。本文档介绍在CentOS 7操作系统的ECS实例上搭建PostgreSQL主从架构的操作步骤。
|
SQL 存储 关系型数据库
PostgreSQL 流复制搭建主从环境,同步和异步的解释,压力测试,主从角色切换|学习笔记
快速学习PostgreSQL 流复制搭建主从环境,同步和异步的解释,压力测试,主从角色切换
734 0
PostgreSQL 流复制搭建主从环境,同步和异步的解释,压力测试,主从角色切换|学习笔记
|
SQL 存储 Oracle
PostgreSQL 事务隔离级别的实现和多版本并发控制|学习笔记
快速学习 PostgreSQL 事务隔离级别的实现和多版本并发控制
433 0
PostgreSQL 事务隔离级别的实现和多版本并发控制|学习笔记
|
SQL 存储 关系型数据库
9 PostgreSQL 点对点多主表级复制-触发器篇|学习笔记
快速学习9 PostgreSQL 点对点多主表级复制-触发器篇
343 0
9 PostgreSQL 点对点多主表级复制-触发器篇|学习笔记
|
存储 SQL Oracle
10 PostgreSQL 表级复制-物化视图篇, 支持异地,异构如 Oracle 到 pg 的物化视图|学习笔记
快速学习10 PostgreSQL 表级复制-物化视图篇,支持异地,异构如 Oracle 到 pg 的物化视图
423 0
10 PostgreSQL 表级复制-物化视图篇, 支持异地,异构如 Oracle 到 pg 的物化视图|学习笔记
|
存储 SQL 缓存
PostgreSQL 复制原理及高可用集群(一)|学习笔记
快速学习 PostgreSQL 复制原理及高可用集群(一)
337 0
PostgreSQL 复制原理及高可用集群(一)|学习笔记
|
SQL 消息中间件 算法
14 PostgreSQL 表级复制-Londiste3哈希数据分区复制|学习笔记
快速学习14 PostgreSQL 表级复制-Londiste3哈希数据分区复制
127 0
14 PostgreSQL 表级复制-Londiste3哈希数据分区复制|学习笔记
|
SQL 消息中间件 存储
PostgreSQL 表级复制-Londiste3安装以及使用|学习笔记
快速学习 PostgreSQL 表级复制-Londiste3安装以及使用
303 0
PostgreSQL 表级复制-Londiste3安装以及使用|学习笔记
|
关系型数据库 测试技术 PostgreSQL
postgresql实现影响分析
通过postgresql模仿分析假如城市发布通知,位于街道的人员是否受到了影响
97 0
postgresql实现影响分析