复制延迟时间

本页面介绍如何排查和修复 Cloud SQL 读取副本的复制延迟问题。

概览

Cloud SQL 读取副本使用 PostgreSQL 流式复制功能。更改会写入主实例中的预写式日志 (WAL)。 WAL 发送者将 WAL 发送到副本中的 WAL 接收者,在其中应用它们。

在几种情况下可能会发生复制延迟,例如:

  • 主实例将更改发送到副本的速度不够快。
  • 副本接收更改的速度不够快。
  • 副本无应用更改的速度不够快。
您可以使用 network_lag 指标监控上述前两个原因。第三个原因通过 replica_lag 指标观察。replica_lag 高表示副本无法足够快速地应用复制更改。您可以通过 replica_byte_lag 指标观察总延迟,该指标具有指示更多详情的标签。下面的监控复制延迟时间部分介绍了这些指标。

确保副本预配充足

如果副本实例小于主实例(例如,vCPU 和内存较少),可能会出现复制延迟。与较大的主实例相比,较小的副本可能还具有不同的默认配置标志。我们建议副本实例至少与主实例一样大,以便有足够的资源来处理复制负载。

副本上的高 CPU 利用率也可能导致复制延迟。如果副本的 CPU 利用率过高(例如超过 90%),请考虑增加副本的 CPU 容量。

您可以使用 SHOW ALL 命令查看副本和主实例配置,并比较它们之间的差异。

优化查询和架构

本部分建议一些可用于提高复制性能的常见查询和架构优化。

读取副本中长时间运行的查询

副本中的长时间运行的查询可能会阻止 Cloud SQL 的复制。当复制尝试将更改(例如来自 VACUUM 操作的更改)应用到副本上正在被查询读取的行时,可能会发生这种情况。

您可能希望使用单独的副本进行在线事务处理 (OLTP) 和在线分析处理 (OLAP),并且仅将长时间运行的查询发送到 OLAP 副本。

为了帮助解决由长时间运行的事务导致的复制延迟或阻塞,我们建议执行以下操作:

  • 调整备用延迟标志。max_standby_archive_delaymax_standby_streaming_delay 标志控制副本在取消与复制冲突的备用查询之前等待的时间。合理的值通常约为 30 到 60 秒。您可以查看 pg_stat_database_conflicts 视图,获取有关查询冲突的分析洞见。
  • 启用 hot_standby_feedback 标志。将副本中的 hot_standby_feedback 标志设置为 on,有助于延迟主实例上的完全清理 (vacuum) 操作。不过,这可能会导致主实例上的表膨胀,因此需要权衡利弊。

如需了解详情,请参阅 PostgreSQL 文档

高网络延迟

高网络延迟表明主实例发送 WAL 记录或副本接收 WAL 记录的速度不够快。这可能是由以下原因导致的:

  • 跨区域复制。在不同区域之间进行复制可能会导致更高的网络延迟。
  • 主实例 CPU 利用率过高。如果主实例的 CPU 利用率超过 90%,则 WAL 发送程序进程可能无法获得足够的 CPU 时间。请考虑减少主实例上的负载或增加其 CPU。
  • 副本 CPU 利用率过高。如果副本的 CPU 利用率超过 90%,则 WAL 接收程序进程可能无法获得足够的 CPU 时间。请考虑减少副本上的负载或增加其 CPU。
  • 网络带宽问题或磁盘 I/O 瓶颈。选择距离更近的区域或配置更高的磁盘吞吐量可能会有所帮助。请考虑修改主实例中的 wal_compression 标志值,以帮助减少跨区域流量。
您可以使用 cloudsql.googleapis.com/database/replication/network_lag 指标监控网络延迟。即使实际延迟更高,此指标的最大限值也为 25 秒。

network_lag 指标类似于 cloudsql.googleapis.com/database/postgresql/replication/replica_byte_lag 指标,后者根据其 replica_lag_type 标签指示的字节数来衡量 sent_location 延迟。

DDL 导致的独占锁定

数据定义语言 (DDL) 命令(例如 ALTER TABLECREATE INDEX)可能会导致副本因独占锁定而出现复制延迟。为避免锁定争用,请考虑在副本上的查询负载较低期间安排 DDL 执行。

如需了解详情,请参阅 PostgreSQL 文档

过载的副本

如果读取副本收到的查询过多,则系统可能会阻止复制。请考虑在多个副本之间拆分读取,以减少每个副本的负载。

为了避免查询高峰,请考虑在应用逻辑或代理层(如果使用代理层)中限制副本读取查询。

如果主实例上出现活动峰值,请考虑分散更新。

单体式主数据库

请考虑将主数据库垂直(或水平)分片,以防止一个或多个滞后表阻止其他所有表。

监控复制延迟

您可以使用 replica_lagnetwork_lag 指标来监控复制延迟,并确定延迟原因在于主数据库、网络还是副本。

指标说明
复制延迟
(cloudsql.googleapis.com/database/replication/replica_lag)

副本状态晚于主实例状态的秒数。这是当前时间与主数据库提交当前应用于副本的事务的原始时间戳之间的差值。具体而言,如果副本尚未将写入应用于数据库,则即使它们接收了写入,写入操作也可能被视为滞后。

此指标是使用副本中的 now() - pg_last_xact_replay_timestamp() 计算的。这是一个近似值。如果复制中断,则副本不会知道主数据库的进度,并且此指标不会指示总延迟。

延迟字节数
(cloudsql.googleapis.com/database/postgres/replication/replica_byte_lag)

副本状态滞后于主数据库状态的字节数。replica_byte_lag 会导出 4 个时序,replica_lag_type 标签可以表示以下任意一项:

  • sent_location::表示已生成但尚未发送到副本的 WAL 字节数。
  • write_location::写入字节数减去发送延迟字节数表示网络中已发出但尚未在副本中写入的 WAL 字节数。
  • flush_location::Flush 字节数减去写入延迟字节数表示副本中已写入但尚未 flush 的 WAL 字节数。
  • replay_location::显示总延迟(以字节为单位)。重放减去清空延迟时间表示重放延迟时间。
网络延迟
(cloudsql.googleapis.com/database/replication/network_lag)

从在主数据库中提交到抵达副本中的 WAL 接收器所需的秒数。

如果 network_lag 为零或可以忽略,但 replica_lag 较高,则表示 WAL 接收者应用复制更改的速度不够快。

验证复制

如需验证复制是否正常工作,请对副本运行以下语句:

  select status, last_msg_receipt_time from pg_stat_wal_receiver;

如果正在进行复制,您会看到状态 streaming 和最近的 last_msg_receipt_time:

  postgres=> select status, last_msg_receipt_time from pg_stat_wal_receiver;
    status   |     last_msg_receipt_time
  -----------+-------------------------------
  streaming | 2020-01-21 20:19:51.461535+00
  (1 row)

如果未发生复制,则返回空结果:

  postgres=> select status, last_msg_receipt_time from pg_stat_wal_receiver;
  status | last_msg_receipt_time
  --------+-----------------------
  (0 rows)

后续步骤: