5

我正在通过 JDBC 驱动程序创建从 AWS Postgres RDS 到 java 进程的复制槽和流式更改。

我的复制槽创建代码如下所示。

final ReplicationSlotInfo replicationSlotInfo = pgConnection.getReplicationAPI()
                    .createReplicationSlot()
                    .logical()
                    .withSlotName(replicationSlotName)
                    .withOutputPlugin("wal2json")
                    .make();

我使用以下代码获得复制流。

pgConnection.getReplicationAPI()
                .replicationStream()
                .logical()
                .withSlotName(replicationSlotName)
                .withSlotOption("include-xids", true)
                .withSlotOption("include-timestamp", true)
                .withSlotOption("pretty-print", false)
                .withSlotOption("add-tables", "public.users")
                .withStatusInterval(10, TimeUnit.SECONDS)
                .start()

当复制器 java 进程未运行时,WAL 大小会增加。这是我用来查找复制滞后的查询。

SELECT
    slot_name,
    pg_size_pretty(pg_xlog_location_diff(pg_current_xlog_location(), restart_lsn)) AS replicationSlotLag,
    active
FROM
    pg_replication_slots;

输出:

slot_name   replicationslotlag  active
data_stream_slot    100 GB  f

这种复制延迟会超过 RDS 磁盘,这会关闭 RDS。

我以为wal_keep_segments会解决这个问题,它设置为 32。但它没有用。是否有任何其他属性我必须设置以避免这种情况,即使 Java 复制进程没有运行。

4

3 回答 3

5

一个提议允许限制逻辑复制槽 WAL 保留。我认为这正是您所需要的,但尚不清楚何时/是否可用。

与此同时,你所能做的就是监视情况,然后如果它开始落后太远就放弃它。当然,这确实意味着您稍后会在重新建立同步时遇到问题,但是没有办法解决这个问题(除了修复导致复制过程消失和/或落后的任何问题)。

既然你说java进程没有运行,那么删除插槽很容易。如果它正在运行,但只是没有跟上,那么您将不得不在杀死 wal 发件人的地方跳一段悲伤的小舞,然后尝试在插槽重新启动之前放下插槽(我不知道您是如何做到的) RDS)

wal_keep_segments仅适用于物理复制,不适用于逻辑。它是用来代替插槽的,而不是除它们之外的。如果两者都有,则保留 WAL 直到满足两个条件。确实,这就是您面临的问题;逻辑复制不能像物理复制那样使用插槽。

于 2020-03-04T15:57:25.030 回答
2

wal_keep_segments与逻辑解码无关。

使用逻辑解码时,您始终必须使用逻辑复制槽,这是一种在事务日志 (WAL) 中标记位置的数据结构,因此服务器永远不会丢弃逻辑解码可能仍需要的旧 WAL 段。

这就是如果您不使用更改,您的 WAL 目录会增长的原因。

wal_keep_segments指定要保留的旧 WAL 段的最小数量。它用于流复制pg_receivewalpg_rewind.

于 2020-03-04T13:34:01.503 回答
0

wal_keep_segments指定PostgreSQL 应该在目录中保留的最小段数。pg_xlogPostgreSQL 不删除段可能有几个原因:

  1. 在比 WAL 文件更旧的 WAL 位置有一个复制槽,您可以使用以下查询检查它:
SELECT slot_name,
       lpad((pg_control_checkpoint()).timeline_id::text, 8, '0') ||
       lpad(split_part(restart_lsn::text, '/', 1), 8, '0') ||
       lpad(substr(split_part(restart_lsn::text, '/', 2), 1, 2), 8, '0')
       AS wal_file
FROM pg_replication_slots;
  1. WAL 归档已启用但archive_command失败。请在这种情况下检查 PostgreSQL 日志。

  2. 很长一段时间没有检查站。

于 2020-03-04T13:36:38.380 回答