主从复制的两种形式
1)基于文件的日志传送
创建一个高可用性(HA)集群配置可采用连续归档,集群中主服务器工作在连续归档模式下,备服务器工作在连续恢复模式下(1台或多台可随时接管主服务器),备持续从主服务器读取WAL文件。连续归档不需要对数据库表做任何改动,可有效降低管理开销,对主服务器的性能影响也相对较低。直接从一个数据库服务器移动WAL记录到另一台服务器被称为日志传送,PostgreSQL通过一次一文件(WAL段)的WAL记录传输实现了基于文件的日志传送。日志传送所需的带宽取根据主服务器的事务率而变化;日志传送是异步的,即WAL记录是在事务提交后才被传送,那么在一个窗口期内如果主服务器发生灾难性的失效则会导致数据丢失,还没有被传送的事务将会被丢失;数据丢失窗口可以通过使用参数archive_timeout进行限制,可以低至数秒,但同时会增加文件传送所需的带宽。archive_timeout强制N秒以后进行一次归档,若设置太小,很快就会超过wal_keep_segments 的值,导致数据覆盖丢失,因此不要盲目设置。
2)流复制
PostgreSQL在9.x之后引入了主从的流复制机制,所谓流复制,就是备服务器通过tcp流从主服务器中同步相应的数据,主服务器在WAL记录产生时即将它们以流式传送给备服务器,而不必等到WAL文件被填充。默认情况下流复制是异步的,这种情况下主服务器上提交一个事务与该变化在备服务器上变得可见之间客观上存在短暂的延迟,但这种延迟相比基于文件的日志传送方式依然要小得多,在备服务器的能力满足负载的前提下延迟通常低于一秒;在流复制中,备服务器比使用基于文件的日志传送具有更小的数据丢失窗口,不需要采用archive_timeout来缩减数据丢失窗口;PostgreSQL 12开始,在执行通过流复制来配置主备数据库的时候,不再需要配置额外配置recovery.conf文件了。取而代之的是在备库环境的$PGDATA路径下配置一个standby.signal文件,注意该文件是一个普通的文本文件,内容为空。理解起来就是,该文件是一个标识文件。如果备库通过执行pg_ctl promote提升为主库的话,那么该文件将自动消失。
附注:
在data目录下增加recovery.conf文件操作
standby_mode='on'
recovery_target_timeline = 'latest'
primary_conninfo='host=172.16.106.61 port=5432 user=standby password=standby'
trigger_file='/data/pgsql/qgzhdc01/trigger_node'
192.168.1.200 | pgsql-master |
192.168.1.201 | pgsql-slave |
参考上一篇1分钟搞定pgsql部署,pgsql-slave可以配置到初始化节点一步就不再继续,通过后面的步骤直接加入主库就ok
master与slave执行:
ssh-keygen -t rsa
ssh-copy-id pgsql-slave
ssh-copy-id pgsql-master
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
ssh postgres@pgsql-slave 测试是否成功互通
ssh postgres@pgsql-master 测试是否成功互通
修改配置文件postgressql.conf
$ vim /usr/local/pgsql/data/postgresql.conf
# 监听所有IP
listen_addresses = "*"
# 最大连接数,据说从机需要大于或等于该值
max_connections = 200
# 设置主pgsql为生成wal的主机,9.6开始没有hot_standby(热备模式)
wal_level = replica
# 开启连续归档
archive_mode = on
#归档命令。-o "StrictHostKeyChecking no" 作用是取消第一次连接输入yes或者no
archive_command = 'scp -o "StrictHostKeyChecking no" %p pgsql-slave:/usr/local/pgsql/data/%
f'
archive_cleanup_command = '/usr/local/pgsql/bin/pg_archivecleanup -d /usr/local/pgsql/data/
pg_wal %r && /usr/local/pgsql/bin/pg_archivecleanup -d /usr/local/pgsql/data/ %r >> /usr/lo
cal/pgsql/data/pgsql/log/archive_cleanup.log 2>&1'
# 最多有16个流复制连接。
max_wal_senders = 16
# 设置流服务保留的最多wal(老版本叫xlog)文件个数
wal_keep_segments = 256(部分版本设置会报错,原因不详)
# 数据堆清理的最大进程
autovacuum_max_workers = 2
max_worker_processes = 16
max_logical_replication_workers = 10
# 这台机器不仅用于数据归档,还可以用于数据查询(配置读写分离可以关闭)
hot_standby = on
# 日志设置
wal_log_hints = on
log_destination = 'stderr'
logging_collector = on
log_directory = '/usr/local/pgsql/data/pgsql/log'
log_filename = 'pgsql-%w.log'
log_file_mode = 0600
log_truncate_on_rotation = on
log_rotation_age = 1d
log_rotation_size = 1GB
log_min_messages = error
# 执行超过300ms的sql语句会记录到pgsql的日志文件,类似于慢日志
# 一般设置300ms就好,慢日志会打到pgsql日志文件,方便查问题
log_min_duration_statement = 300
log_checkpoints = on
log_connections = on
log_disconnections = on
log_error_verbosity = verbose
log_hostname = on
log_line_prefix = '%m [%p] '
log_lock_waits = on
log_statement = 'ddl'
修改pg_hba.conf
$vim /usr/local/pgsql/data/pg_hba.conf
host replication replica 192.168.0.0/16 md5
重启服务:(源码包安装操作)
pg_ctl -D /usr/local/pgsql/data/ restart
主库创建具有流复制权限的用户replica
psql
CREATE user replica login replication encrypted password '123456‘;
postgres=# \du;
List of roles
Role name | Attributes | Member of
-----------+------------------------------------------------------------+-----------
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
replica | Replication | {}
编译安装后不初始化
su - postgres
sudo mkdir -p /usr/local/pgsql/data
sudo chmod 750 /usr/local/pgsql/data/pgsql/log
sudo chown postgres.postgres /usr/local/pgsql/data/pgsql/log
从主服务器上copy数据到从服务器,这一步叫做“基础备份
$ pg_basebackup -h 192.168.1.200 -p 5432 -U replica -W -R -Fp -Xs -Pv -D /usr/local/pgsql/data/
Password:
pg_basebackup: initiating base backup, waiting for checkpoint to complete
pg_basebackup: checkpoint completed
pg_basebackup: write-ahead log start point: 0/8000028 on timeline 1
pg_basebackup: starting background WAL receiver
pg_basebackup: created temporary replication slot "pg_basebackup_13370"
31384/31384 kB (100%), 1/1 tablespace
pg_basebackup: write-ahead log end point: 0/8000100
pg_basebackup: waiting for background process to finish streaming ...
pg_basebackup: syncing data to disk ...
pg_basebackup: base backup completed
参数说明:
选项 说明
-p 主库数据库端口
-U 流复制用户
-W 使用密码验证,要用replica的密码
-Fp 备份输出正常的数据库目录
-Xs 使用流复制的方式进行复制
-Pv 输出复制过程的详细信息
-R 为备库创建recovery.conf文件。但是pgsql 10以后的新版本的pgsql不需要这个文件了。
-D 指定创建的备库的数据库目录
注意:这时候,从库数据目录下的postgresql.conf文件是刚才从主的pgsql上同步过来的,并不是pgsql的配置文件,你需要将原先老的从库上的配置文件拿过来用。
$ cd /usr/local/pgsql/data/
$ mv postgres.conf postgres.conf_master.bak
$ vim postgres.conf
# 监听所有IP
listen_addresses = "*"
port = 5432
# 最大连接数,从pgsql需要大于或等于主的值
max_connections = 300
restore_command = 'cp /usr/local/pgsql/data/%f %p'
archive_cleanup_command = 'archive_cleanup_command = '/usr/local/pgsql/bin/pg_archivecleanup -d /usr/local/pgsql/data/pg_wal %r && /usr/local/pgsql/bin/pg_archivecleanup -d /usr/local/pgsql/data/ %r >> /usr/lo
cal/pgsql/data/pgsql/log/archive_cleanup.log 2>&1''
# 9.6开始没有hot_standby(热备模式)
wal_level = replica
# 最多有16个流复制连接。
max_wal_senders = 16
# 设置比主库大,可以设置为2倍的数值
wal_keep_segments = 512
max_logical_replication_workers = 10
autovacuum_max_workers = 2
# 和主的值保持一致即可
max_worker_processes = 16
# 说明这台机器不仅用于数据归档,还可以用于数据查询
hot_standby = on
#流备份的最大延迟时间
max_standby_streaming_delay = 30s
# 向主机汇报本机状态的间隔时间
wal_receiver_status_interval = 10s
# 出现错误复制,向主机反馈
hot_standby_feedback = on
# 日志设置
log_destination = 'stderr'
logging_collector = on
log_directory = '/data/postgresql-12/log'
log_filename = 'postgresql-%w.log'
log_file_mode = 0600
log_truncate_on_rotation = on
log_rotation_age = 1d
log_rotation_size = 1GB
log_min_messages = error
# 执行超过300ms的sql语句会被记录到pgsql的日志文件中
log_min_duration_statement = 300
log_checkpoints = on
log_connections = on
log_disconnections = on
log_error_verbosity = verbose
log_hostname = on
log_line_prefix = '%m [%p] '
log_lock_waits = on
log_statement = 'ddl'
重启从库
要保证从库的数据目录是postgres属主和属组,且权限为0700
su - postgres
pg_ctl -D /usr/local/pgsql/data restart
验证pgsql主从
postgres=# psql
postgres=# select client_addr,sync_state from pg_stat_replication;
client_addr | sync_state
--------------+------------
192.168.1.201 | async
(1 row)
select pid, usename, application_name, client_addr,
backend_start, client_port, state, sync_state from pg_stat_replication;
pid | usename | application_name | client_addr | backend_start | client_port | state | sync_state
-------+---------+------------------+-------------+-------------------------------+-------------+-----------+------------
28356 | repl | walreceiver | 192.168.1.201 | 2021-12-30 17:00:59.357653+08 | 48660 | streaming | async
(1 row)
// 以上说明192.168.1.201服务器是从节点 //
验证pgsql主从流复制:
#登录主库,可以读写:
[postgres@pgsql-master data]$ psql
psql (14.0)
Type "help" for help.
postgres=# select * from test;
id
----
1
(1 row)
postgres=# create table test0(id int);
CREATE TABLE
postgres=# insert into test0 values(1);
INSERT 0 1
postgres=# select * from test0;
id
----
1
(1 row)
postgres=#
#登录从库,流复制模式下,从库没有写权限,但是可以读
[postgres@pgsql-slave data]$ psql
psql (14.0)
Type "help" for help.
postgres=# create table test0(id int);
ERROR: cannot execute CREATE TABLE in a read-only transaction
postgres=# insert into test0 values(1);
ERROR: cannot execute INSERT in a read-only transaction
postgres=# select * from test0;
id
----
1
(1 row)
postgres=#
主库插入表格test0,从库可以读取,主从流复制完成