前言:
postgresql数据库是一个比较先进的中型关系型数据库,原本以为repmgr和基于repmgr的主从复制是挺简单的一个事情,但现实很快就给我教育了,原来postgresql和MySQL一样的,也是有异步或者同步的复制区别的
PostgreSQL直到目前版本(截至2024年4月)并未内置原生的半同步复制功能,不像MySQL那样有明确的半同步复制选项。然而,PostgreSQL提供了两种复制模式,分别是异步复制和同步复制:
-
异步复制:这是PostgreSQL默认的复制模式,主节点在事务提交时不等待备节点确认,备节点通过流复制接收并应用主节点的WAL日志。
-
同步复制:在PostgreSQL中,可以通过设置
synchronous_commit
参数和synchronous_standby_names
参数来实现一定程度的同步复制。当synchronous_commit
设置为on
时,主节点在提交事务时会等待至少一个备节点确认收到WAL记录。通过synchronous_standby_names
可以指定至少有多少个备节点必须确认,或者指定特定备节点名称。
尽管严格意义上的“半同步”概念在PostgreSQL中没有直接对应的实现,但通过上述配置可以模拟近似的效果,即在某种程度上平衡数据一致性与性能。然而,这种同步复制并不是真正的“半同步”,因为它要么是等待所有指定的备节点确认(同步),要么是不等待任何备节点确认(异步)。
这里的意思是一主多从(从数量至少为2),可以指定单独的某个或者多个从的synchronous_standby_names
而不是所有的从节点,没有指定的从节点自然就是在异步复制模式,这样就实现了异步和同步复制的混合
一,
查询主从是哪种复制模式
本例中我只有两个postgresql服务器组成的主从,主节点是192.168.123.17,从节点是192.168.123.20,主从是基于repmgr搭建的
repmgr高可用搭建见上一篇博客:Linux|centos7-postgresql数据库|yum安装数据库和配置repmgr高可用集群以及repmgr的日常管理工作-CSDN博客
查询方法1
在主节点执行以下命令查询,该命令是直接读取postgresql的主配置文件,根据配置文件的内容返回内容的:
SELECT name, setting, unit FROM pg_settings WHERE name IN ('synchronous_commit', 'synchronous_standby_names');
输出如下:
此时这两个值有内容表示是同步复制,否则为异步复制
查询方法2
这个命令也是比较准确的:
select sync_state from pg_stat_replication;
输出为sync,表示是同步复制,否则为异步模式,如果有多个值表示混合复制模式
查询方法3
通过pg_controldata命令,Latest checkpoint location,Latest checkpoint's REDO location, Latest checkpoint's oldestXID这三个值都一模一样表示是同步复制,否则是异步复制
主节点:
[root@centos7 ~]# pg_controldata
pg_control version number: 1201
Catalog version number: 201909212
Database system identifier: 7351900556498275811
Database cluster state: in production
pg_control last modified: Wed 03 Apr 2024 06:32:04 AM CST
Latest checkpoint location: 0/B9000028
Latest checkpoint's REDO location: 0/B9000028
Latest checkpoint's REDO WAL file: 0000000600000000000000B9
Latest checkpoint's TimeLineID: 6
Latest checkpoint's PrevTimeLineID: 6
Latest checkpoint's full_page_writes: on
Latest checkpoint's NextXID: 0:458006
Latest checkpoint's NextOID: 303174
Latest checkpoint's NextMultiXactId: 1
Latest checkpoint's NextMultiOffset: 0
Latest checkpoint's oldestXID: 479
Latest checkpoint's oldestXID's DB: 1
Latest checkpoint's oldestActiveXID: 0
Latest checkpoint's oldestMultiXid: 1
Latest checkpoint's oldestMulti's DB: 1
Latest checkpoint's oldestCommitTsXid:0
Latest checkpoint's newestCommitTsXid:0
Time of latest checkpoint: Wed 03 Apr 2024 06:32:04 AM CST
Fake LSN counter for unlogged rels: 0/3E8
Minimum recovery ending location: 0/0
Min recovery ending loc's timeline: 0
Backup start location: 0/0
Backup end location: 0/0
End-of-backup record required: no
wal_level setting: logical
wal_log_hints setting: on
max_connections setting: 1000
max_worker_processes setting: 8
max_wal_senders setting: 10
max_prepared_xacts setting: 0
max_locks_per_xact setting: 64
track_commit_timestamp setting: off
Maximum data alignment: 8
Database block size: 8192
Blocks per segment of large relation: 131072
WAL block size: 8192
Bytes per WAL segment: 16777216
Maximum length of identifiers: 64
Maximum columns in an index: 32
Maximum size of a TOAST chunk: 1996
Size of a large-object chunk: 2048
Date/time type storage: 64-bit integers
Float4 argument passing: by value
Float8 argument passing: by value
Data page checksum version: 0
Mock authentication nonce: e76af00554364729517eece5fa0fcf6f7f0662da3a154cabb730c2ab24edd267
从节点:
pg_control version number: 1201
Catalog version number: 201909212
Database system identifier: 7351900556498275811
Database cluster state: in archive recovery
pg_control last modified: Wed 03 Apr 2024 06:30:41 AM CST
Latest checkpoint location: 0/B8000028
Latest checkpoint's REDO location: 0/B8000028
Latest checkpoint's REDO WAL file: 0000000600000000000000B8
Latest checkpoint's TimeLineID: 6
Latest checkpoint's PrevTimeLineID: 6
Latest checkpoint's full_page_writes: on
Latest checkpoint's NextXID: 0:458006
Latest checkpoint's NextOID: 303174
Latest checkpoint's NextMultiXactId: 1
Latest checkpoint's NextMultiOffset: 0
Latest checkpoint's oldestXID: 479
Latest checkpoint's oldestXID's DB: 1
Latest checkpoint's oldestActiveXID: 0
Latest checkpoint's oldestMultiXid: 1
Latest checkpoint's oldestMulti's DB: 1
Latest checkpoint's oldestCommitTsXid:0
Latest checkpoint's newestCommitTsXid:0
Time of latest checkpoint: Wed 03 Apr 2024 06:30:35 AM CST
Fake LSN counter for unlogged rels: 0/3E8
Minimum recovery ending location: 0/B80000A0
Min recovery ending loc's timeline: 6
Backup start location: 0/0
Backup end location: 0/0
End-of-backup record required: no
wal_level setting: logical
wal_log_hints setting: on
max_connections setting: 1000
max_worker_processes setting: 8
max_wal_senders setting: 10
max_prepared_xacts setting: 0
max_locks_per_xact setting: 64
track_commit_timestamp setting: off
Maximum data alignment: 8
Database block size: 8192
Blocks per segment of large relation: 131072
WAL block size: 8192
Bytes per WAL segment: 16777216
Maximum length of identifiers: 64
Maximum columns in an index: 32
Maximum size of a TOAST chunk: 1996
Size of a large-object chunk: 2048
Date/time type storage: 64-bit integers
Float4 argument passing: by value
Float8 argument passing: by value
Data page checksum version: 0
Mock authentication nonce: e76af00554364729517eece5fa0fcf6f7f0662da3a154cabb730c2ab24edd267
二,
设置复制为同步模式(不设置自然的就是默认模式了)
首先检查postgresql.auto.conf 这个文件,看primary_conninfo的值里有没有包含application_name 这样的字样,如果有就是同步复制模式,否则就是异步复制模式
查看此配置文件的原因是有些时候某些操作会自动写此文件,而该文件的优先等级又非常的高,也就是此文件里又的内容会生效,不管postgresql.conf 里写了什么都没用,这个文件内的配置是必定生效
如果没有application_name,那么是异步复制模式,此时需要更改postgresql.conf,主要是以下两个配置项:
synchronous_commit ,该选项有多个值,一般是使用remote_write
synchronous_commit
参数在PostgreSQL中用于控制事务提交时对同步复制的要求级别。它的设置可以根据对数据一致性和性能的不同需求进行调整。以下是几个常见的设置值:
-
on: 这是最保守的设置,意味着在事务提交时,主节点会等待所有已知的同步备节点确认WAL记录已写入磁盘。这对于要求最高数据一致性的场景是理想选择,但可能会降低写入性能。
-
remote_write: 这个设置意味着主节点只需要等待至少一个同步备节点将WAL记录写入其操作系统缓存即可,不需要确认数据已落到磁盘。相比
on
,remote_write
减少了等待时间,但增加了在备节点未将缓存写入磁盘前发生故障导致数据丢失的风险。 -
remote_apply: 更进一步,设置为
remote_apply
时,主节点不仅等待备节点写入WAL记录,还需要等待备节点将事务应用到数据库中。这是最高的同步复制一致性级别,但也是性能影响最大的设置。 -
off: 这个设置禁用了同步复制,主节点在事务提交时不等待任何备节点的反馈,此时所有的备节点都变成异步复制,主节点的写入性能最高,但数据安全性最低,这个是默认设置,也就是默认是异步复制
-
local:这个设置表示事务仅在本机提交就可以了,不管是否同步到了从节点
选择哪种设置取决于业务需求和容忍的数据丢失风险。在repmgr管理的PostgreSQL集群中,通常会根据业务需求权衡数据安全性与性能来选择合适的synchronous_commit
设置。如果需要较高数据一致性且备节点足够可靠,remote_write
可能是一个常用的选择,但仍需结合具体应用场景分析。
synchronous_commit = remote_write # synchronization level;# off, local, remote_write, remote_apply, or on
#wal_sync_method = fsync # the default is the first option# supported by the operating system:# open_datasync# fdatasync (default on Linux)# fsync# fsync_writethrough# open_sync
synchronous_standby_names
synchronous_standby_names = '*' # standby servers that provide sync rep# method to choose sync standbys, number of sync standbys,# and comma-separated list of application_name# from standby(s); '*' = all
如何知道这个该写哪个呢?如果有多个从节点,不希望全部是同步复制,只希望指定的是同步复制模式,很简单,下面的SQL语句查询就可以,第三个:
select * from pg_stat_replication;
repmgr的主配置文件里也有,例如node_name='pg2' ,这个是从节点的repmgr的主配置文件;如果希望全部都是同步复制模式(多从节点的时候),那么简单的一个星号就可以了
这两个配置选项设置好后,就可以重启主节点,让同步复制生效了
小结:
postgresql.conf
和postgresql.auto.conf这两个配置文件里的配置要一致,不要一个是同步复制,一个是异步复制,那样可能会造成混乱,有的时候会使主库暂停服务。而同步复制可以提高数据安全,因为时时刻刻主从的数据都是一致的嘛,但这也是一个双刃剑,如果从库挂了或者由于网络,从库磁盘等等问题,导致同步复制会进行不下去,那么,主库可能要hang住
在同步复制的环境中,如果一个从库(备库)挂了,其对主库(源库)的影响取决于具体采用的同步策略:
-
对于全同步复制(MySQL中并没有原生的全同步复制,这里假设是一种所有从库都需确认的极端情况),如果任何从库不可用,则主库无法执行新的事务直至从库恢复在线。这意味着主库将暂停对外服务,因为它在等待所有从库确认事务,这种情况下系统的可用性大大降低。
-
对于半同步复制(MySQL的Semi-Synchronous Replication),主库在执行完事务后至少等待一个从库确认才会返回成功给客户端。在这种情况下,如果唯一的半同步从库挂了,主库会等待超时(默认是几秒钟,可通过
rpl_semi_sync_master_timeout
参数调整)后变为异步模式继续服务,以免阻塞事务提交。这样,虽然不会像全同步那样立刻导致主库无法服务,但如果长期缺少半同步从库,数据安全性则退化为异步复制级别。 -
对于一般的异步复制环境,从库挂了并不会直接影响主库的服务,主库仍然可以接收并执行新的事务,只是这部分未被已挂掉从库同步的事务在从库恢复前不会出现在从库上。
总结来说,在同步复制的场景下,从库挂掉会导致以下几种可能影响:
- 全同步复制:主库事务处理阻塞,系统整体可用性下降。
- 半同步复制:主库可能会有短暂延迟,然后转为异步模式,数据安全性减弱但不影响服务可用性。
- 异步复制:主库不受影响,但从库上的数据将落后于主库,直到从库重新上线并恢复同步。
在异步复制的场景中,如果一个从库(备库)挂了,对主库(源库)的影响相对较小:
-
主库操作不受影响:主库会继续处理客户端的读写请求,事务提交不会因为从库的离线而延迟或阻止。异步复制的特点是主库在接收到事务提交请求后,无需等待从库确认就返回给客户端事务已提交,因此主库本身的性能和可用性不受从库状态影响。
-
数据一致性:从库挂掉时,这段时间内主库产生的新的事务不会立即同步到该从库,因此该从库的数据会落后于主库,直至从库恢复并完成同步。
-
高可用性和灾备:如果主库发生故障,由于从库未能及时跟上主库的数据,可能无法立即作为新的主库接管服务,除非你能接受一定的数据丢失。在高可用性场景下,通常会配置多个从库,其中一个或多个从库作为潜在的故障切换候选,以减少单个从库故障带来的风险。
-
监控与恢复:从库挂掉时,需要及时检测并恢复从库服务,以确保后续能够继续进行复制,保持数据的一致性和满足灾备需求。
总之,在异步复制中,从库挂掉不会直接影响主库的工作,但会影响整个集群的数据一致性、高可用性和灾备能力,因此需要及时监控和处理从库故障。