流式复制
来自 PostgreSQL wiki
跳转到导航跳转到搜索流式复制 (SR) 提供了连续传输和应用 WAL XLOG 记录到一些备用服务器上的功能,以保持它们同步。
此功能在 PostgreSQL 9.0 中添加。 以下讨论面向开发人员,其中包含一些过时信息,尤其是在 PostgreSQL 10 及更高版本中。此功能的用户应参考当前的 PostgreSQL 流式复制文档.
项目开发人员和历史细节
SR 由 NTT OSS 中心开发,用于在 PostgreSQL 9.0 中使用。 主要开发人员是 Masao Fujii。 同步日志传输复制演示 介绍了该功能的早期设计。
用法
用户概述
- 日志传输
- 在主服务器上生成的 XLOG 记录会定期通过网络传输到备用服务器。
- 在现有的热备用中,只有已填充的文件中的记录会被传输,这被称为基于文件的日志传输。 在 SR 中,部分填充的 XLOG 文件中的 XLOG 记录也会被传输,实现了基于记录的日志传输。 这意味着 SR 中的数据丢失窗口通常小于热备用中的窗口,除非热备用也配置为基于记录的传输(这在设置方面很复杂)。
- 写入备用服务器的 XLOG 文件内容与主服务器上的内容完全相同。 传输的 XLOG 文件可用于正常恢复和 PITR。
- 多个备用服务器
- 多个备用服务器可以与主服务器建立连接以进行 SR。 XLOG 记录会同时传输到所有这些备用服务器。 备用服务器的延迟或故障不会影响到其他备用服务器的日志传输。
- 备用服务器的最大数量可以指定为 GUC 变量。
- 持续恢复
- 备用服务器会持续重放传输的 XLOG 记录,而无需使用 pg_standby。
- 传输的 XLOG 记录会尽快被重放,而不会等到 XLOG 文件被完全填充。 热备用 和 SR 的组合将使插入到主服务器中的最新数据几乎立即在备用服务器中可见。
- 备用服务器会定期删除不再需要用于恢复的旧 XLOG 文件,以防止磁盘占用过多。
- 设置
- 日志传输的开始不会干扰主服务器上的任何查询处理。
- 备用服务器可以在各种条件下启动。
- 如果存档目录中存在 XLOG 文件,并且提供了 restore_command,那么首先会重放这些文件。 然后备用服务器会向主服务器请求最后一个应用的 XLOG 记录后面的 XLOG 记录。 这可以防止备用服务器上已存在的 XLOG 文件再次被传输。 同样,pg_xlog 中的 XLOG 文件也会在开始日志传输之前被重放。
- 如果没有备用服务器上的 XLOG 文件,备用服务器会请求恢复的起始 XLOG 位置(重做起始位置)后面的 XLOG 记录。
- 连接设置和身份验证
- 用户可以将与正常连接到 SR 的连接相同的设置(例如,keepalive、pg_hba.conf)配置到 SR 的连接。
- 激活
- 备用服务器可以一直等到激活,只要用户愿意。 这可以防止备用服务器因恢复失败或网络中断而自动启动。
- 进度报告
- 主服务器和备用服务器会在 PS 显示中报告日志传输的进度。
- 优雅关闭
- 当请求智能/快速关闭时,主服务器会等到 XLOG 记录已发送到备用服务器,直到关闭检查点记录才会退出。
限制
- 同步日志传输
- 默认情况下,SR 支持以异步方式运行,因此提交命令可能会在相应的 XLOG 记录被传输到备用服务器之前向客户端返回“成功”。 要启用同步复制,请参阅 同步复制
- 跨时间线复制
- 用户需要在使旧的备用服务器赶上来时获取一个新的备份。
- 集群
- Postgres 没有提供任何集群功能。
使用方法
注意:本节与 二进制复制教程 有重叠部分
- 1. 在主服务器和备用服务器上像往常一样安装 postgres。 这只需要configure、make 和make install。
- 2. 使用initdb 在主服务器上创建初始数据库集群,像往常一样。
- 3. 创建一个名为 replication 的用户,具有 REPLICATION 权限。
$ CREATE ROLE replication WITH REPLICATION PASSWORD 'password' LOGIN;
- 4. 在主服务器上设置连接和身份验证,以便备用服务器能够成功连接到主服务器上的replication 伪数据库。
$ $EDITOR postgresql.conf listen_addresses = '192.168.0.10'
$ $EDITOR pg_hba.conf # The standby server must connect with a user that has replication privileges. # TYPE DATABASE USER ADDRESS METHOD host replication replication 192.168.0.20/32 md5
- 5. 在主服务器上设置与流式复制相关的参数。
$ $EDITOR postgresql.conf # To enable read-only queries on a standby server, wal_level must be set to # "hot_standby". But you can choose "archive" if you never connect to the # server in standby mode. wal_level = hot_standby # Set the maximum number of concurrent connections from the standby servers. max_wal_senders = 5 # To prevent the primary server from removing the WAL segments required for # the standby server before shipping them, set the minimum number of segments # retained in the pg_xlog directory. At least wal_keep_segments should be # larger than the number of segments generated between the beginning of # online-backup and the startup of streaming replication. If you enable WAL # archiving to an archive directory accessible from the standby, this may # not be necessary. wal_keep_segments = 32 # Enable WAL archiving on the primary to an archive directory accessible from # the standby. If wal_keep_segments is a high enough number to retain the WAL # segments required for the standby server, this is not necessary. archive_mode = on archive_command = 'cp %p /path_to/archive/%f'
- 6. 在主服务器上启动 postgres。
- 7. 通过将主服务器的数据目录复制到备用服务器来进行基础备份。
- 7.1. 在主服务器上使用 pg_(start|stop)_backup 和 rsync 进行操作
$ psql -c "SELECT pg_start_backup('label', true)" $ rsync -ac ${PGDATA}/ standby:/srv/pgsql/standby/ --exclude postmaster.pid $ psql -c "SELECT pg_stop_backup()"
- 7.2. 在备用服务器上使用 pg_basebackup 进行操作
在 9.1+ 版本中,pg_basebackup 可以完成从主服务器获取整个 PostgreSQL 安装数据目录并将其放置到备用服务器上的繁琐工作。
先决条件是确保备用服务器的数据目录为空。
确保也删除了任何表空间目录。 可以使用以下命令查找这些目录:
$ psql -c '\db'
如果将 postgresql.conf 和其他配置文件放在 PGDATA 中,则需要备份 postgresql.conf,以便在 pg_basebackup 后恢复。
在清理所有目录后,可以使用以下命令直接将数据从主服务器流式传输到备用服务器。 以数据库超级用户(通常是 'postgres')身份运行,以确保权限得到保留(使用 su、sudo 或其他任何工具来确保你不是 root)。
$ pg_basebackup -h 192.168.0.10 -D /srv/pgsql/standby -P -U replication --xlog-method=stream
在 9.3+ 版本中,还可以添加 -R 选项,以便它为下面的步骤 9 创建一个最小恢复命令文件。
如果备份了 postgresql.conf,现在将其恢复。
- 8. 在备用服务器上设置与复制相关的参数、连接和身份验证,就像主服务器一样,以便备用服务器在故障转移后可以作为主服务器工作。
- 9. 在备用服务器上启用只读查询。 但是,如果主服务器上的 wal_level 是archive,则保持 hot_standby 不变(即关闭)。
$ $EDITOR postgresql.conf hot_standby = on
- 10. 在备用服务器上创建恢复命令文件;以下参数是流式复制所需的。
$ $EDITOR recovery.conf # Note that recovery.conf must be in the $PGDATA directory, even if the # main postgresql.conf file is located elsewhere. # Specifies whether to start the server as a standby. In streaming replication, # this parameter must to be set to on. standby_mode = 'on' # Specifies a connection string which is used for the standby server to connect # with the primary. primary_conninfo = 'host=192.168.0.10 port=5432 user=replication password=password' # Specifies a trigger file whose presence should cause streaming replication to # end (i.e., failover). trigger_file = '/path_to/trigger' # Specifies a command to load archive segments from the WAL archive. If # wal_keep_segments is a high enough number to retain the WAL segments # required for the standby server, this may not be necessary. But # a large workload can cause segments to be recycled before the standby # is fully synchronized, requiring you to start again from a new base backup. restore_command = 'cp /path_to/archive/%f "%p"'
- 11. 在备用服务器上启动 postgres。 它将开始流式复制。
- 12. 可以通过将主服务器上的当前 WAL 写入位置与备用服务器接收/重放的最后一个 WAL 位置进行比较来计算复制延迟。 它们分别可以通过主服务器上的pg_current_xlog_location 和备用服务器上的pg_last_xlog_receive_location/pg_last_xlog_replay_location 来获取。
$ psql -c "SELECT pg_current_xlog_location()" -h192.168.0.10 (primary host) pg_current_xlog_location -------------------------- 0/2000000 (1 row) $ psql -c "select pg_last_xlog_receive_location()" -h192.168.0.20 (standby host) pg_last_xlog_receive_location ------------------------------- 0/2000000 (1 row) $ psql -c "select pg_last_xlog_replay_location()" -h192.168.0.20 (standby host) pg_last_xlog_replay_location ------------------------------ 0/2000000 (1 row)
- 13. 还可以使用ps 命令检查流式复制的进度。
# The displayed LSNs indicate the byte position that the standby server has # written up to in the xlogs. [primary] $ ps -ef | grep sender postgres 6879 6831 0 10:31 ? 00:00:00 postgres: wal sender process postgres 127.0.0.1(44663) streaming 0/2000000 [standby] $ ps -ef | grep receiver postgres 6878 6872 1 10:31 ? 00:00:01 postgres: wal receiver process streaming 0/2000000
- 如何进行故障转移
- 主服务器发生故障后,在备用服务器上创建触发文件。
- 如何停止主服务器或备用服务器
- 像往常一样关闭它(pg_ctl stop)。
- 如何故障转移后重新启动流式复制
- 重复从第 6 步开始的操作;进行新的备份、一些配置,然后将原来的主服务器作为备用服务器启动。 在这些操作期间,不需要停止主服务器。
- 如何备用服务器发生故障后重新启动流式复制
- 消除故障原因后,重新启动备用服务器上的 postgres。
- 如何断开备用服务器与主服务器的连接
- 在主服务器运行时,在备用服务器上创建触发文件。 然后备用服务器将被启动。
- 如何隔离后重新同步独立的备用服务器
- 像往常一样关闭备用服务器。 然后重复从第 6 步开始的操作。
- 如果有多个备用服务器,提升其中一个将破坏其他备用服务器。 更新其 recovery.conf 设置以指向新的主服务器,将 recovery_target_timeline 设置为“latest”,使用 scp/rsync 复制 pg_xlog 目录,然后重新启动备用服务器。
待办事项
v9.0
已提交
- 从存档中重试以及围绕 Read/FetchRecord() 的一些重构。 - 提交
- SR 错误地处理了 WAL 边界。 - 提交
- 针对一些关于 wal 跳过的后期更改调整 SR。 - 提交
- VACUUM FULL 意外地写入了一个 XLOG UNLOGGED 记录。 - 提交
- 添加消息类型头。 - 提交
- 文档:添加新的“复制”章节。 - 提交
- 在部分 WAL 文件恢复期间出现断言失败。 - 提交
- 由于部分填充的存档 WAL 文件,备用服务器可能会出现 PANIC 错误。 - 提交
- 改进备用服务器消息。 - 提交
- pq_getbyte_if_available() 无法工作,因为 win32 套接字模拟层根本没有设计用于处理非阻塞套接字。 - 提交
- Walsender 可能会发出不合适的邮件。 - 提交
- 在 win32 上的流式复制仍然存在问题。 - 提交
- 为 recovery.conf 创建新部分。 - 提交
- walreceiver 中断言失败。 - 提交
- 在恢复期间禁止启动 walsender,并发出合适的错误信息?还是允许在恢复期间启动 walsender? - 提交
- 我们如何不使用 pg_standby 来清理存档? - 提交
- 基于文件的日志传递在没有 pg_standby 的情况下不会在 pg_xlog 中重放 WAL 文件。 - 提交
v9.1
同步功能
- 引入复制模式,该模式可以控制事务提交在返回“成功”给客户端之前等待复制的时间。有效的模式是 *异步*、*接收* 和 *fsync*。
- *异步* 不会让事务提交等待复制,即异步复制。
- *接收* 或 *fsync* 分别使事务提交等待 XLOG 被备机接收或 fsync。
- (*应用* 使事务提交等待 XLOG 被备机重放。此模式将在 v9.2 或更高版本中支持)
- 复制模式在备机的 recovery.conf 中指定,以及复制的其他参数。
- 启动过程从 recovery.conf 读取复制模式并通过新的共享内存变量将其共享给 walreceiver。
- Walreceiver 还通过使用复制握手消息将其共享给 walsender(现有的协议需要扩展)。
- 根据复制模式,walreceiver 向主节点发送回复,表示复制已完成到指定位置。
- 在异步模式下,walreceiver 不需要发送任何回复,除了复制结束消息。
- 在接收或 fsync 模式下,walreceiver 分别在接收或刷新 XLOG 后立即发送回复。
- 需要定义回复的新消息类型。回复作为 CopyData 消息发送。
- Walreceiver 在关闭之前将所有未完成的 XLOG 写入磁盘。
- Walsender 接收来自备机的回复,更新最后复制记录的位置,并宣布复制完成。
- 需要新的共享内存变量来保存该位置。
- 在处理提交命令时,后端会等待 XLOG 复制到所有处于接收或 fsync 复制模式的备机。
- 同样,智能关闭会等待关闭检查点的 XLOG 被复制。
- 所需优化
- Walsender 应该在不等待 wal_sender_delay 的情况下发送未完成的 XLOG。
- 在处理提交命令时,后端会向 walsender 发送信号,立即发送未完成的 XLOG。
- 后端应该在回复到达主节点后立即退出等待循环。
- 在收到回复时,walsender 会向后端发送信号,让它们从睡眠状态恢复,并通过检查最后复制的 XLOG 的位置来确定是否退出等待循环。
- 仅向等待 XLOG 复制到回复中包含的位置的后端发送信号。
- Walsender 使用 select/poll 同时等待来自后端的信号和来自备机的回复。
- Walsender 不仅从磁盘读取 XLOG,还从共享内存(wal 缓冲区)读取。
- Walreceiver 应该仅在 XLOG 文件切换或相关页面被刷新时刷新 XLOG 文件。
- 当启动过程或 bgwriter 刷新缓冲区页面时,它会检查相关 XLOG 是否已通过共享内存(最后刷新 XLOG 的位置)刷新。
- 如果 XLOG 文件已刷新,则刷新缓冲区页面。
- 如果 XLOG 文件尚未刷新,则向 walreceiver 发送信号,立即刷新 XLOG 文件并等待刷新完成。
- 当备机正在赶上主节点时,这些服务器应该忽略复制模式并执行异步复制。
- 当这些服务器几乎同步时,它们会根据指定的复制模式执行复制。
- 需要定义新的复制状态,如“追赶中”、“同步”等,并且这两个服务器都需要状态机。
- 当前复制状态可以通过 SQL 在两个服务器上监控。
- Walsender 应该在不等待 wal_sender_delay 的情况下发送未完成的 XLOG。
- 所需超时
- 添加新的参数 replication_timeout,它是等待 XLOG 复制到备机的最大时间。(这是否与 https://postgresql.ac.cn/docs/current/interactive/runtime-config-replication.html 一致?)
- 添加新参数 (replication_timeout_action) 来指定对 replication_timeout 的反应。
未来版本
- 同步功能
- 引入同步模式,该模式可以控制事务提交在返回“成功”给客户端之前等待复制的时间。有效的模式是 *异步*、*接收*、*fsync* 和 *应用*。
- *异步* 不会让事务提交等待复制,即异步复制。
- *接收*、*fsync* 和 *应用* 使事务提交分别等待 XLOG 记录被备机接收、fsync 和应用。
- 更改 walsender 以便能够不仅从磁盘读取 XLOG,还从共享内存读取 XLOG。
- 添加新的参数 replication_timeout,它是等待 XLOG 记录复制到备机的最大时间。(这是否与 https://postgresql.ac.cn/docs/current/interactive/runtime-config-replication.html 一致?)
- 添加新参数 (replication_timeout_action) 来指定对 replication_timeout 的反应。
- 引入同步模式,该模式可以控制事务提交在返回“成功”给客户端之前等待复制的时间。有效的模式是 *异步*、*接收*、*fsync* 和 *应用*。
- 监控
- 提供通过一个查询检查流式复制的进度和差距的能力。HS 和 SR 的协作对于在备机端提供该功能是必要的。
- 提供通过查询检查指定复制是否正在进行的能力。此外,可能需要更详细的状态信息,例如,备机正在赶上,已经同步等等。
- 更改统计收集器以收集有关复制的统计信息,例如复制时间的平均延迟。
- 开发从 XLOG 文件计算最新 XLOG 位置的工具。这对于在服务器故障后检查复制的差距是必要的。
- 此外,开发从 XLOG 文件中提取用户可读内容的工具。这对于查看差距的内容并手动还原它们是必要的。
- 易于使用
- 引入以下参数:
- replication_halt_timeout - 如果在这么长时间内没有发送数据,则复制将停止。
- replication_halt_segments - 如果 pg_xlog 中的 WAL 文件数量超过此阈值,则复制将停止。
- 这些参数允许我们避免磁盘溢出。
- 添加新功能,该功能还通过主节点和备机之间的直接连接传输基本备份。
- 添加新的钩子,如 walsender_hook 和 walreceiver_hook,以便与压缩附加程序(如 pglesslog)协作。
- 提供通过主节点上的查询优雅地终止复制的功能。在备机端,触发文件机制已经提供了该功能。
- 支持跨时间线复制。时间线历史文件需要从主节点发送到备机。
- 引入以下参数:
- 鲁棒性
- 支持 libpq 中的保持活动连接。这对客户端和备机立即检测主节点故障很有用。
- 其他
- 独立的 walreceiver 工具,它连接到主节点,持续接收和写入 XLOG 记录,独立于 postgres 服务器。
- 级联流式复制。允许 walsender 在恢复期间向另一个备机发送 XLOG。
- 恢复期间的 WAL 归档。