本节概述如何在 1 个或多个数据库副本上设置异步流复制。
在 Timescale 上免费试用
Timescale 是一款完全托管的服务,提供自动备份和恢复、复制的高可用性、无缝扩展和调整大小等等。您可以免费试用 Timescale 30 天。
在开始之前,请确保您至少运行了 2 个独立的 TimescaleDB 实例。如果您使用 Docker 容器安装了 TimescaleDB,请使用 PostgreSQL 入口脚本 运行配置。有关更高级的示例,请参见 Timescale Helm Charts 存储库。
要配置自托管 TimescaleDB 上的复制,您需要执行以下步骤
要配置主数据库,您需要一个具有允许其初始化流复制的角色的 PostgreSQL 用户。每个副本使用此用户从主数据库进行流式传输。
在主数据库上,以具有超级用户权限的用户(例如
postgres
用户)的身份,将密码加密级别设置为scram-sha-256
SET password_encryption = 'scram-sha-256';创建一个名为
repuser
的新用户CREATE ROLE repuser WITH REPLICATION PASSWORD '<PASSWORD>' LOGIN;
重要
scram-sha-256
密码加密级别是 PostgreSQL 中最安全的基于密码的身份验证方式。它仅在 PostgreSQL 10 及更高版本中可用。
在 postgresql.conf
配置文件中,需要添加或编辑多个复制设置。
- 将
synchronous_commit
参数设置为off
。 - 将
max_wal_senders
参数设置为来自副本或备份客户端的并发连接总数。至少,这应该等于您打算拥有的副本数量。 - 将
wal_level
参数设置为写入 PostgreSQL 预写日志 (WAL) 的信息量。要使复制正常工作,WAL 中需要有足够的数据来支持归档和复制。默认值通常是合适的。 - 将
max_replication_slots
参数设置为主数据库可以支持的复制槽总数。 - 将
listen_addresses
参数设置为主数据库的地址。不要将此参数保留为本地环回地址,因为远程副本必须能够连接到主服务器才能流式传输 WAL。 - 重新启动 PostgreSQL 以获取更改。这必须在您创建复制槽之前完成。
最常见的流复制用例是使用一个或多个副本进行异步复制。在此示例中,WAL 会流式传输到副本,但主服务器不会等待确认 WAL 是否已写入副本上的磁盘。这是性能最高的复制配置,但它确实存在系统故障时可能丢失少量数据的风险。它也不能保证副本与主服务器完全同步,这会导致主服务器和副本上的读取查询之间出现不一致。此用例的示例配置
listen_addresses = '*'wal_level = replicamax_wal_senders = 2max_replication_slots = 2synchronous_commit = off
如果您需要在副本上获得更强的一致性,或者您的查询负载过重,导致异步模式下主节点和副本节点之间出现明显的延迟,请考虑使用同步复制配置。有关不同复制模式的更多信息,请参见 复制模式部分。
配置完 postgresql.conf
并重新启动 PostgreSQL 后,您可以为每个副本创建 复制槽。复制槽可确保主服务器不会在副本接收到 WAL 段之前将其从 WAL 中删除。如果副本长时间停机,这很重要。主服务器需要验证 WAL 段是否已被副本使用,以便可以安全地删除数据。您可以使用 归档 来实现此目的,但复制槽为流复制提供了最强的保护。
在
psql
槽中,创建第一个复制槽。槽的名称是任意的。在此示例中,它被称为replica_1_slot
SELECT * FROM pg_create_physical_replication_slot('replica_1_slot');对每个所需的复制槽重复此操作。
在 pg_hba.conf
配置文件中,需要添加或编辑多个复制设置。在此示例中,这些设置将复制连接限制为来自 REPLICATION_HOST_IP
的流量,作为具有有效密码的 PostgreSQL 用户 repuser
。REPLICATION_HOST_IP
可以从该机器发起流复制,无需其他凭据。您可以更改 address
和 method
值以匹配您的安全和网络设置。
有关 pg_hba.conf
的更多信息,请参见 pg_hba
文档。
打开
pg_hba.conf
配置文件并添加或编辑以下行TYPE DATABASE USER ADDRESS METHOD AUTH_METHODhost replication repuser <REPLICATION_HOST_IP>/32 scram-sha-256重新启动 PostgreSQL 以获取更改。
副本通过流式传输主服务器的 WAL 日志并在 PostgreSQL 恢复模式下重放其事务来工作。为此,副本需要处于可以重放日志的状态。您可以通过从主实例的基本备份中恢复副本来实现此目的。
停止 PostgreSQL 服务。
如果副本数据库中已经包含数据,请在运行备份之前将其删除,方法是删除 PostgreSQL 数据目录
rm -rf <DATA_DIRECTORY>/*如果您不知道数据目录的位置,请使用
show data_directory;
命令找到它。使用主数据库的 IP 地址和复制用户名从基本备份中恢复
pg_basebackup -h <PRIMARY_IP> \-D <DATA_DIRECTORY> \-U repuser -vP -W-W
标志会提示您输入密码。如果您在自动化设置中使用此命令,您可能需要使用 pgpass 文件。备份完成后,在您的数据目录中创建一个 standby.signal 文件。当 PostgreSQL 在其数据目录中找到
standby.signal
文件时,它将在恢复模式下启动并通过复制协议流式传输 WALtouch <DATA_DIRECTORY>/standby.signal
成功创建基本备份和 standby.signal
文件后,您可以配置复制和恢复设置。
在副本的
postgresql.conf
文件中,添加与主服务器通信的详细信息。如果您使用的是流复制,primary_conninfo
中的application_name
应与主服务器的synchronous_standby_names
设置中使用的名称相同primary_conninfo = 'host=<PRIMARY_IP> port=5432 user=repuserpassword=<POSTGRES_USER_PASSWORD> application_name=r1'primary_slot_name = 'replica_1_slot'添加详细信息以镜像主数据库的配置。如果您使用的是异步复制,请使用以下设置
hot_standby = onwal_level = replicamax_wal_senders = 2max_replication_slots = 2synchronous_commit = offhot_standby
参数必须设置为on
,以允许在副本上执行只读查询。在 PostgreSQL 10 及更高版本中,此设置默认情况下为on
。重新启动 PostgreSQL 以获取更改。
此时,您的副本应与主数据库完全同步并准备好从中进行流式传输。您可以通过检查副本上的日志来验证它是否正常工作,日志应类似于以下内容
LOG: database system was shut down in recovery at 2018-03-09 18:36:23 UTCLOG: entering standby modeLOG: redo starts at 0/2000028LOG: consistent recovery state reached at 0/3000000LOG: database system is ready to accept read only connectionsLOG: started streaming WAL from primary at 0/3000000 on timeline 1
任何客户端都可以在副本上执行读取操作。您可以通过在主数据库上运行插入、更新或其他修改来验证这一点,然后查询副本以确保它们已正确复制。
在大多数情况下,异步流复制就足够了。但是,您可能需要在主服务器和副本之间获得更高的一致性,尤其是在工作负载较重的情况下。在工作负载过重的情况下,副本可能会远远落后于主服务器,从而向从副本读取的客户端提供陈旧的数据。此外,在任何数据丢失都是致命的的情况下,异步复制可能无法提供足够的持久性保证。PostgreSQL 的 synchronous_commit
功能具有多个选项,具有不同的性能和一致性权衡。
在 postgresql.conf
文件中,将 synchronous_commit
参数设置为
on
:这是默认值。在 WAL 事务写入主服务器上的磁盘以及任何副本上的磁盘之前,服务器不会返回success
。off
:当 WAL 事务已发送到操作系统以写入主服务器上的磁盘上的 WAL 时,服务器将返回success
,但不会等待操作系统实际写入它。如果服务器在某些数据尚未写入时崩溃,这会导致少量数据丢失,但不会导致数据损坏。关闭synchronous_commit
是 PostgreSQL 的一个众所周知的优化,适用于能够承受系统崩溃时某些数据丢失的工作负载。local
:仅在主服务器上强制执行on
行为。remote_write
:当 WAL 记录已发送到操作系统以写入副本上的 WAL 时,数据库将向客户端返回success
,但在确认记录已实际持久保存到磁盘之前。这类似于异步提交,但它还会等待副本以及主服务器。实际上,等待副本而产生的额外等待时间会显著减少复制延迟。remote_apply
:要求确认 WAL 记录已写入 WAL 并应用到所有副本上的数据库。这提供了所有synchronous_commit
选项中最强的持久性。在此模式下,副本始终反映主服务器的最新状态,复制延迟几乎不存在。
重要
如果 synchronous_standby_names
为空,则设置 on
、remote_apply
、remote_write
和 local
都提供相同的同步级别,并且事务提交将等待本地刷新到磁盘。
此矩阵显示了每种模式提供的的一致性级别
模式 | WAL 发送到操作系统(主服务器) | WAL 持久化(主服务器) | WAL 发送到操作系统(主服务器和副本) | WAL 持久化(主服务器和副本) | 事务应用(主服务器和副本) |
---|---|---|---|---|---|
关闭 | ✅ | ❌ | ❌ | ❌ | ❌ |
本地 | ✅ | ✅ | ❌ | ❌ | ❌ |
远程写入 | ✅ | ✅ | ✅ | ❌ | ❌ |
开启 | ✅ | ✅ | ✅ | ✅ | ❌ |
远程应用 | ✅ | ✅ | ✅ | ✅ | ✅ |
synchronous_standby_names
设置是 synchronous_commit
的补充设置。它列出了主数据库支持用于同步复制的所有副本的名称,并配置了主数据库如何等待它们。synchronous_standby_names
设置支持以下格式
FIRST num_sync (replica_name_1, replica_name_2)
:这将等待来自前num_sync
个副本的确认,然后返回success
。replica_names
列表决定了副本的优先级。副本名称由副本上的application_name
设置决定。ANY num_sync (replica_name_1, replica_name_2)
:这将等待来自提供的列表中num_sync
个副本的确认,无论它们的优先级或在列表中的位置如何。这可以用作仲裁函数。
同步复制模式强制主服务器等待所有必需的副本写入 WAL 或应用数据库事务,具体取决于 synchronous_commit
级别。如果必需的副本崩溃,这可能会导致主服务器无限期挂起。当副本重新连接时,它会重播任何需要赶上的 WAL。只有这样,主服务器才能恢复写入。为了缓解这种情况,请在 synchronous_standby_names
设置下所需的节点数量之外配置更多节点,并将它们列在 FIRST
或 ANY
子句中。这允许主服务器只要大多数副本已写入最新的 WAL 事务即可继续运行。不在服务的副本能够重新连接并异步重播错过的 WAL 事务。
PostgreSQL pg_stat_replication 视图提供了有关每个副本的信息。此视图对于计算复制延迟特别有用,复制延迟衡量的是副本当前状态落后于主服务器的程度。replay_lag
字段衡量了主服务器上的最新 WAL 事务与副本上最后报告的数据库提交之间的秒数。结合 write_lag
和 flush_lag
,这提供了对副本落后程度的洞察。*_lsn
字段也提供了有用的信息。它们允许您比较主服务器和副本之间的 WAL 位置。state
字段对于确定每个副本当前正在执行的操作非常有用;可用的模式包括 startup
、catchup
、streaming
、backup
和 stopping
。
要在主数据库上查看数据,请运行以下命令
SELECT * FROM pg_stat_replication;
输出如下所示
-[ RECORD 1 ]----+------------------------------pid | 52343usesysid | 16384usename | repuserapplication_name | r2client_addr | 10.0.13.6client_hostname |client_port | 59610backend_start | 2018-02-07 19:07:15.261213+00backend_xmin |state | streamingsent_lsn | 16B/43DB36A8write_lsn | 16B/43DB36A8flush_lsn | 16B/43DB36A8replay_lsn | 16B/43107C28write_lag | 00:00:00.009966flush_lag | 00:00:00.03208replay_lag | 00:00:00.43537sync_priority | 2sync_state | sync-[ RECORD 2 ]----+------------------------------pid | 54498usesysid | 16384usename | repuserapplication_name | r1client_addr | 10.0.13.5client_hostname |client_port | 43402backend_start | 2018-02-07 19:45:41.410929+00backend_xmin |state | streamingsent_lsn | 16B/43DB36A8write_lsn | 16B/43DB36A8flush_lsn | 16B/43DB36A8replay_lsn | 16B/42C3B9C8write_lag | 00:00:00.019736flush_lag | 00:00:00.044073replay_lag | 00:00:00.644004sync_priority | 1sync_state | sync
PostgreSQL 提供了一些故障转移功能,在发生故障时,副本将被提升为主服务器。这是使用 pg_ctl 命令或 trigger_file
提供的。但是,PostgreSQL 不支持自动故障转移。有关更多信息,请参见 PostgreSQL 故障转移文档。如果您需要具有自动故障转移功能的可配置高可用性解决方案,请查看 Patroni。
关键字