Timescale Cloud:性能、扩展、企业级

自托管产品

MST

本节概述了如何在单个或多个数据库副本上设置异步流复制。

在 Timescale 上免费试用

Timescale 是一项完全托管服务,提供自动备份和恢复、带复制功能的高可用性、无缝扩展和调整大小等功能。您可以免费试用 Timescale 三十天。

免费试用

在开始之前,请确保您至少有两个独立的 TimescaleDB 实例正在运行。如果您使用 Docker 容器安装 TimescaleDB,请使用 PostgreSQL 入口点脚本 来运行配置。有关更高级的示例,请参阅 Timescale Helm Charts 仓库

要在自托管 TimescaleDB 上配置复制,您需要执行以下步骤

  1. 配置主数据库
  2. 配置复制参数
  3. 创建复制槽
  4. 配置基于主机的身份验证参数
  5. 在副本上创建基础备份
  6. 配置复制和恢复设置
  7. 验证副本是否正常工作

要配置主数据库,您需要一个具有允许初始化流复制角色的 PostgreSQL 用户。这是每个副本用于从主数据库进行流式传输的用户。

  1. 在主数据库上,以具有超级用户权限(例如 postgres 用户)的用户身份,将密码加密级别设置为 scram-sha-256

    SET password_encryption = 'scram-sha-256';
  2. 创建一个名为 repuser 的新用户

    CREATE ROLE repuser WITH REPLICATION PASSWORD '<PASSWORD>' LOGIN;
重要提示

scram-sha-256 加密级别是 PostgreSQL 中最安全的基于密码的身份验证方式。它仅在 PostgreSQL 10 及更高版本中可用。

postgresql.conf 配置文件中有几个复制设置需要添加或编辑。

  1. synchronous_commit 参数设置为 off
  2. max_wal_senders 参数设置为来自副本或备份客户端的并发连接总数。最小应等于您打算拥有的副本数量。
  3. wal_level 参数设置为写入 PostgreSQL 预写日志 (WAL) 的信息量。为了使复制正常工作,WAL 中需要有足够的数据来支持归档和复制。默认值通常是合适的。
  4. max_replication_slots 参数设置为主数据库可以支持的复制槽总数。
  5. listen_addresses 参数设置为主数据库的地址。不要将此参数保留为本地回环地址,因为远程副本必须能够连接到主数据库以流式传输 WAL。
  6. 重启 PostgreSQL 以应用更改。这必须在创建复制槽之前完成。

最常见的流复制用例是具有一个或多个副本的异步复制。在此示例中,WAL 会流式传输到副本,但主服务器不会等待 WAL 已写入主服务器或副本磁盘的确认。这是性能最高的复制配置,但它确实存在系统故障时少量数据丢失的风险。它也不能保证副本与主服务器完全同步,这可能会导致主服务器和副本上的读取查询之间出现不一致。此用例的示例配置:

listen_addresses = '*'
wal_level = replica
max_wal_senders = 2
max_replication_slots = 2
synchronous_commit = off

如果您需要在副本上获得更强的一致性,或者如果您的查询负载足够重,以至于在异步模式下导致主节点和副本节点之间出现显著延迟,请考虑同步复制配置。有关不同复制模式的更多信息,请参阅复制模式部分

配置 postgresql.conf 并重启 PostgreSQL 后,您可以为每个副本创建一个复制槽。复制槽可确保主服务器在副本接收到 WAL 段之前不会删除它们。这在副本长时间停机的情况下非常重要。主服务器需要验证 WAL 段是否已被副本使用,以便安全地删除数据。您可以为此目的使用归档,但复制槽为流复制提供了最强的保护。

  1. psql 槽位,创建第一个复制槽。槽的名称是任意的。在此示例中,它被称为 replica_1_slot

    SELECT * FROM pg_create_physical_replication_slot('replica_1_slot', true);
  2. 对每个所需的复制槽重复此操作。

有几个复制设置需要添加到 pg_hba.conf 配置文件中或进行编辑。在此示例中,这些设置将复制连接限制为来自 REPLICATION_HOST_IP 的流量,使用 PostgreSQL 用户 repuser 和有效密码。REPLICATION_HOST_IP 可以从该机器启动流复制,无需额外凭据。您可以更改 addressmethod 值以匹配您的安全和网络设置。

有关 pg_hba.conf 的更多信息,请参阅 pg_hba 文档

  1. 打开 pg_hba.conf 配置文件并添加或编辑此行

    TYPE DATABASE USER ADDRESS METHOD AUTH_METHOD
    host replication repuser <REPLICATION_HOST_IP>/32 scram-sha-256
  2. 重启 PostgreSQL 以应用更改。

副本通过流式传输主服务器的 WAL 日志并在 PostgreSQL 恢复模式下重放其事务来工作。为此,副本需要处于可以重放日志的状态。您可以通过从主实例的基础备份中恢复副本来实现这一点。

  1. 停止 PostgreSQL 服务。

  2. 如果副本数据库已包含数据,请在运行备份之前删除它,方法是移除 PostgreSQL 数据目录

    rm -rf <DATA_DIRECTORY>/*

    如果您不知道数据目录的位置,请使用 show data_directory; 命令查找。

  3. 使用主数据库的 IP 地址和复制用户名从基础备份中恢复。

    pg_basebackup -h <PRIMARY_IP> \
    -D <DATA_DIRECTORY> \
    -U repuser -vP -W

    -W 标志会提示您输入密码。如果您在自动化设置中使用此命令,您可能需要使用 pgpass 文件

  4. 备份完成后,在数据目录中创建一个standby.signal文件。当 PostgreSQL 在其数据目录中找到 standby.signal 文件时,它将以恢复模式启动并通过复制协议流式传输 WAL。

    touch <DATA_DIRECTORY>/standby.signal

成功创建基础备份和 standby.signal 文件后,您可以配置复制和恢复设置。

  1. 在副本的 postgresql.conf 文件中,添加与主服务器通信的详细信息。如果您使用的是流复制,primary_conninfo 中的 application_name 应与主服务器 synchronous_standby_names 设置中使用的名称相同

    primary_conninfo = 'host=<PRIMARY_IP> port=5432 user=repuser
    password=<POSTGRES_USER_PASSWORD> application_name=r1'
    primary_slot_name = 'replica_1_slot'
  2. 添加详细信息以镜像主数据库的配置。如果您使用异步复制,请使用这些设置

    hot_standby = on
    wal_level = replica
    max_wal_senders = 2
    max_replication_slots = 2
    synchronous_commit = off

    hot_standby 参数必须设置为 on 以允许在副本上进行只读查询。在 PostgreSQL 10 及更高版本中,此设置默认为 on

  3. 重启 PostgreSQL 以应用更改。

至此,您的副本应已与主数据库完全同步,并准备好从中进行流式传输。您可以通过检查副本上的日志来验证其是否正常工作,日志应如下所示:

LOG: database system was shut down in recovery at 2018-03-09 18:36:23 UTC
LOG: entering standby mode
LOG: redo starts at 0/2000028
LOG: consistent recovery state reached at 0/3000000
LOG: database system is ready to accept read only connections
LOG: 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 为空,则 onremote_applyremote_writelocal 设置都提供相同的同步级别,并且事务提交会等待本地刷新到磁盘。

此矩阵显示了每种模式提供的一致性级别。

模式WAL 发送到操作系统(主)WAL 持久化(主)WAL 发送到操作系统(主和副本)WAL 持久化(主和副本)事务已应用(主和副本)
本地
远程写入
远程应用

synchronous_standby_names 设置是 synchronous_commit 的补充设置。它列出了主数据库支持同步复制的所有副本的名称,并配置了主数据库如何等待它们。synchronous_standby_names 设置支持以下格式:

  • FIRST num_sync (replica_name_1, replica_name_2):这会等待前 num_sync 个副本的确认,然后才返回 successreplica_names 列表决定了副本的相对优先级。副本名称由副本上的 application_name 设置决定。
  • ANY num_sync (replica_name_1, replica_name_2):这会等待所提供列表中 num_sync 个副本的确认,无论其优先级或在列表中的位置如何。这用作仲裁功能。

同步复制模式强制主服务器等待所有必需的副本写入 WAL 或应用数据库事务(取决于 synchronous_commit 级别)。如果所需的副本崩溃,这可能会导致主服务器无限期挂起。当副本重新连接时,它会重放任何需要追赶的 WAL。只有到那时,主服务器才能恢复写入。为了缓解这种情况,请在 synchronous_standby_names 设置下配置比所需节点数量更多的节点,并将它们列在 FIRSTANY 子句中。这允许主服务器只要有足够数量的副本写入了最新的 WAL 事务即可继续进行。停止服务的副本能够异步重新连接并重放错过的 WAL 事务。

PostgreSQL pg_stat_replication视图提供了关于每个副本的信息。此视图对于计算复制延迟特别有用,复制延迟衡量了副本当前状态与主数据库之间的差距。replay_lag 字段衡量了主数据库上最新 WAL 事务与副本上最后报告的数据库提交之间的秒数。结合 write_lagflush_lag,这提供了关于副本落后程度的洞察。*_lsn 字段也提供了有用的信息,允许您比较主数据库和副本之间的 WAL 位置。state 字段有助于精确确定每个副本当前正在做什么;可用模式包括 startupcatchupstreamingbackupstopping

要查看数据,请在主数据库上运行此命令

SELECT * FROM pg_stat_replication;

输出如下所示

-[ RECORD 1 ]----+------------------------------
pid | 52343
usesysid | 16384
usename | repuser
application_name | r2
client_addr | 10.0.13.6
client_hostname |
client_port | 59610
backend_start | 2018-02-07 19:07:15.261213+00
backend_xmin |
state | streaming
sent_lsn | 16B/43DB36A8
write_lsn | 16B/43DB36A8
flush_lsn | 16B/43DB36A8
replay_lsn | 16B/43107C28
write_lag | 00:00:00.009966
flush_lag | 00:00:00.03208
replay_lag | 00:00:00.43537
sync_priority | 2
sync_state | sync
-[ RECORD 2 ]----+------------------------------
pid | 54498
usesysid | 16384
usename | repuser
application_name | r1
client_addr | 10.0.13.5
client_hostname |
client_port | 43402
backend_start | 2018-02-07 19:45:41.410929+00
backend_xmin |
state | streaming
sent_lsn | 16B/43DB36A8
write_lsn | 16B/43DB36A8
flush_lsn | 16B/43DB36A8
replay_lsn | 16B/42C3B9C8
write_lag | 00:00:00.019736
flush_lag | 00:00:00.044073
replay_lag | 00:00:00.644004
sync_priority | 1
sync_state | sync

PostgreSQL 提供了一些故障转移功能,即在发生故障时将副本提升为主数据库。这可以通过使用 pg_ctl命令或 trigger_file 来实现。然而,PostgreSQL 不支持自动故障转移。有关更多信息,请参阅 PostgreSQL 故障转移文档。如果您需要具有自动故障转移功能的可配置高可用性解决方案,请查看 Patroni

关键词

在此页面上发现问题?报告问题 或在 GitHub 上编辑此页面