haha029

PostgreSQL流复制

1 介绍

        PostgresSQL在9.0版本实现的复制功能只能进行异步复制,在PostgreSQL 9.1版本中可以支持同步复制

        PostgreSQL流复制是基于WAL日志传输实现的:主库发送WAL日志,备库接收WAL日志并进行回放。

 

流复制的3个主要进程:

  • 主库的walsender进程:负责发送WAL日志给备库。
  • 备库的walreceiver进程:负责主库发送的WAL日志。
  • 备库的startup进程:重放接收的WAL日志。

 

主从之间是怎么通信的?

(1)primary端 后端进程通过执行函数XLogInsert()和XLogFlush(),将WAL数据写入并刷新到WAL段文件中。

(2)primary端 WAL发送器进程将写入WAL段文件的WAL数据发送到WAL接收器进程。

(3)primary端 在发送WAL数据之后,后端进程继续等待来自备库的ACK响应。更确切地说,后端进程通过执行内部函数SyncRepWaitForLSN()来获取锁存器,并等待它被释放。

(4)standby端 上的WAL接收器通过write()系统函数调用,将接收到的WAL数据写入备库的WAL段,并向WAL发送器返回ACK响应。

(5)standby端 WAL接收器通过调用(如fsync()函数)将WAL数据刷新到WAL段中,向WAL发送器返回另一个ACK响应,并通知启动进程相关WAL数据已更新。

(6)standby端 启动进程重放已写入WAL段的WAL数据。

(7)primary端 WAL发送器在收到来自WAL接收器的ACK响应后释放后端进程的锁存器,然后后端进程完成commit或abort动作。锁存器释放的时间取决于参数synchronous_commit。如果它是‘on’(默认),那么当接收到步骤(5)的ACK时,锁存器被释放;如果它是\'remote_write\',当接收到步骤(4)的ACK时,其被释放。

 

每个ACK响应将备库的内部信息通知给主库,包含以下4个项目:

  • 已写入最新WAL数据的LSN位置。
  • 已刷新最新WAL数据的LSN位置。
  • 启动进程已经重放最新的WAL数据的LSN。
  • 发送此响应的时间戳。

2 安装PostgreSQL

2.1 安装依赖包

[root]# yum install -y perl-ExtUtils-Embed python-devel bison flex readline-devel zlib-devel wget gcc gcc-c++

2.2 创建postgres用户

[root]# useradd postgres
[root]# echo "postgres" | passwd postgres --stdin

2.3 安装UUID

[root]# wget ftp://ftp.ossp.org/pkg/lib/uuid/uuid-1.6.2.tar.gz
[root]# tar -zxvf uuid-1.6.2.tar.gz
[root]# cd uuid-1.6.2
[root]# ./configure --with-uuid=ossp
[root]# make && make install

2.4 源码安装PG

[root]# wget https://ftp.postgresql.org/pub/source/v9.6.0/postgresql-9.6.0.tar.gz
[root]# tar -zxf postgresql-9.6.0.tar.gz
[root]# cd postgresql-9.6.0
[root]# ./configure --prefix=/usr/local/postgresql-9.6.0 --with-perl --with-python --enable-thread-safety --with-uuid=ossp
[root]# make && make install

[root]# ln -s /usr/local/postgresql-9.6.0/ /usr/local/pgsql
[root]# chown -R postgres:postgres /usr/local/postgresql-9.6.0
[root]# chown -R postgres:postgres /usr/local/pgsql

[root]# ln -s /usr/local/lib/libuuid.so.16 /usr/local/pgsql/lib/
[root]# [root]# chown postgres:postgres /usr/local/pgsql/lib/

2.5 安装contrib工具

[root]# cd postgresql-9.6.0/contrib
[root]# make && make install

2.6 配置环境变量

[root]# vi /home/postgres/.bashrc
export PGDATA=/usr/local/pgsql/data
export PATH=/usr/local/pgsql/bin:$PATH
export LD_LIBRARY_PATH=/usr/local/pgsql/lib

2.7 initdb初始化

[root]# mkdir -p $PGDATA
[root]# chown -R postgres:postgres $PGDATA
[root]# ln -s $PGDATA /usr/local/pgsql/data
[root]# chown -R postgres:postgres /usr/local/pgsql/data
[postgres]# initdb -D $PGDATA -k

 3 配置复制流

3.1 primary端

 创建复制用户

postgres=# create role repl login replication encrypted password \'postgres\';
CREATE ROLE

 

配置权限配置文件

[postgres]# vi pg_hba.conf
添加如下:
host replication repl 0.0.0.0/0        md5

 

 配置参数(这个必须配置)

[postgres]# vi postgresql.conf
listen_addresses = \'*\'
wal_level = replica
archive_mode = on
archive_command = \'cp %p /var/lib/pgsql/9.6/arch_log/%f\'

 

重启PG

[postgres]# pg_ctl restart

 3.2 配置standby端

 删除standby端数据

[postgres]# pg_ctl stop
[postgres]# rm -fr $PGDATA/*

 

配置primary端到standby端

[postgres]# pg_basebackup -h 192.168.2.221 -U repl -D $PGDATA -X stream --progress

 

配置recovery.conf文件

[postgres]# vi $PGDATA/recovery.conf
standby_mode = on
primary_conninfo = \'host=192.168.2.221 port=5432 user=repl password=postgres\'
recovery_target_timeline = \'latest\'
trigger_file = \'/tmp/trigger_file0\'

 

备机开启只读

[postgres]# vi $PGDATA/postgressql.conf
hot_standby = on

 3.3 启动流复制

启动standby端PG以启动复制流

[postgres]# pg_ctl start

 

查看流复制详情

postgres=# \x on;
Expanded display is on.
postgres=# select * from pg_stat_replication;
----+------------------------------
pid              | 116077
usesysid         | 16384
usename          | repl
application_name | walreceiver
client_addr      | 10.150.57.9
client_hostname  | 
client_port      | 45984
backend_start    | 2021-12-20 16:17:58.493769+08
backend_xmin     | 
state            | streaming
sent_location    | 89/A2BE8E10
write_location   | 89/A2BE8E10
flush_location   | 89/A2BE8E10
replay_location  | 89/A2BE8E10
sync_priority    | 0
sync_state       | async

4 流复制管理

4.1 主从切换

查看primary端状态

[postgres]# pg_controldata | grep "Database cluster state:"
Database cluster state:               in production

 

查看standby端状态

[postgres]# pg_controldata | grep "Database cluster state:"
Database cluster state:               in archive recovery

 

standby切换为primary

[postgres]# pg_ctl promote -D $PGDATA 
server promoting

4.2 复制槽

        standby端如果长时间停机,重启后standby可能因缺少相应的WAL日志无法连接primary。此时可以通过启用max_replication_slots参数启用复制槽来解决此问题。

        primary端实例会一直保留预写日志(WAL)文件,直到所有备库所需的插槽都确认已接收到特定段为止。只有完成此操作后,主库实例才会移除相应的WAL文件。

 

创建复制槽

SELECT * FROM pg_create_physical_replication_slot(\'pg_primary\');

 

查看复制槽

postgres=# select * from pg_replication_slots;
 slot_name  | plugin | slot_type | datoid | database | active | active_pid | xmin | catalog_xmin | restart_lsn | confirmed_flush_lsn 
------------+--------+-----------+--------+----------+--------+------------+------+--------------+-------------+---------------------
 pg_primary |        | physical  |        |          | t      |     116077 |      |              | 89/A40003E0 | 

 

standby端使用复制槽

[postgres]# vi $PGDATA/recovery.conf
添加如下内容:
primary_slot_name = \'pg_primary\'

 

分类:

技术点:

相关文章:

  • 2022-12-23
  • 2021-12-26
  • 2021-11-12
  • 2021-12-26
  • 2021-12-26
  • 2021-12-26
  • 2021-09-16
猜你喜欢
  • 2022-12-23
  • 2021-11-10
  • 2021-12-26
  • 2022-02-01
  • 2021-09-26
  • 2022-12-23
相关资源
相似解决方案