PostgreSQL: 仲裁者集合的同步备机

John Doe 八月 5, 2025

你想要确保数据库永远不丢失数据吗?PostgreSQL 的同步复制可以做到这一点。

草原上的一头大象

基于仲裁的同步复制

PostgreSQL 10 为synchronous_standby_names配置参数新增了以下语法。通过使用FIRSTANY关键字,用户可以指定从所列服务器中选择同步备用节点的方法。

FIRST num_sync (standby_name [, ...])
ANY num_sync (standby_name [, ...])

关键字FIRST指定了一种基于优先级的同步复制方式,这种方式在 9.6 及之前的版本中也可使用。该方法使事务提交等待,直到其 WAL 记录被复制到根据优先级选择出的num_sync个同步备用节点。

关键字ANY指定了一种基于仲裁者数目的同步复制方式,使事务提交等待,直到其 WAL 记录被复制到所列备用节点中至少num_sync个节点。在这种方法中,所列备用节点在pg_stat_replication中的sync_state值会被报告为 “quorum”(仲裁者)。每个备用节点仍会被分配优先级,但在此方法中不会使用。

不包含FIRSTANY关键字的原有语法仍然受支持。它们与带有FIRST关键字的新语法相同,即基于优先级的同步复制。

示例

PostgreSQL 9.6 版本通过扩展synchronous_standby_names的语法,引入了指定多个同步备用节点的功能。例如,像 “N (standby_1,standby_2, … ,standby_M)” 这样的值,允许主服务器在事务提交时,根据备用节点的可用性及其报告的 WAL 写入、应用或刷新位置(由参数synchronous_commit控制),从用户指定的 M 个节点集合中等待 N 个备用节点的提交确认。不过,在这种情况下,需要等待确认的备用节点是根据它们在该参数列表中的顺序来选择的。

能够定义同步备用节点的仲裁者集合,在一些高可用场景中提供了更高的灵活性。简而言之,可以在收到 N 个备用节点的确认后验证提交,这些备用节点可以是synchronous_standby_names中所列 M 个节点中的任意节点。因此,例如在主服务器带有两个或更多备用节点的部署中,该特性有助于更灵活地选择同步备用节点。不过需要注意的是,最好保证每个节点之间的延迟较低。

PostgreSQL 10 为了支持该特性,synchronous_standby_names的语法扩展了一组关键字。

ANY对应仲裁者集合的行为,意味着集合中的任何节点都可用于确认提交。

FIRST对应 9.6 版本的行为,优先选择列表中靠前的节点(即定义的优先级更高)。

这些关键字的使用示例如下:

# 两个节点的仲裁者集合
any 2 (node_1,node_2)
# 两个节点的高优先级备机集合,包含三个备用节点
first 2 (node_1,node_2,node_3)

还需要注意的是,为了向后兼容,不使用任何关键字时等同于使用 “first”。并且这些关键字不区分大小写。

最后需要了解的是,pg_stat_replication会将仲裁者集合中的备用节点标记为 “quorum”。例如,假设有一个主服务器和两个备用节点node_1node_2

ALTER SYSTEM SET synchronous_standby_names = 'ANY 2(node_1,node_2)';

SELECT pg_reload_conf();
 pg_reload_conf
----------------
 t
(1 row)

以下是它们向用户展示的方式:

SELECT application_name, sync_priority, sync_state FROM pg_stat_replication;
 application_name | sync_priority | sync_state
------------------+---------------+------------
 node_1           |             1 | quorum
 node_2           |             2 | quorum
(2 rows)

需要注意的是,优先级数字在仲裁者集合中没有太大意义,但如果用户希望从 “ANY” 切换到 “FIRST”,查看这些优先级有助于了解切换后哪些备用节点会被视为同步节点。

非常不错的体验,希望这个特性能帮助到你。