PostgreSQL 流复制

PostgreSQLBeginner
立即练习

介绍

在本实验中,你将学习如何配置 PostgreSQL 流复制。这项强大的功能允许你在一个辅助服务器(称为副本)上维护主数据库的实时、只读副本。副本会持续接收并应用来自主服务器的数据更改,这对于高可用性、读查询负载均衡和备份非常有用。

你将完成整个过程,首先配置主服务器以允许复制。然后,通过创建基础备份来创建副本服务器。最后,你将启动副本,测试两个服务器之间的数据流,并了解副本如何与主服务器保持同步。

这是一个实验(Guided Lab),提供逐步指导来帮助你学习和实践。请仔细按照说明完成每个步骤,获得实际操作经验。根据历史数据,这是一个 初级 级别的实验,完成率为 92%

配置主服务器以进行复制

在第一步中,你将配置主 PostgreSQL 服务器,为复制做好准备。这包括修改其配置文件以允许网络连接,启用必要的预写日志 (WAL) 级别,并创建一个用于复制的特殊用户。

1. 修改 PostgreSQL 配置文件

为了准备复制,你需要修改主配置文件 postgresql.conf。使用 nano 等文本编辑器手动编辑这个庞大的文件可能会很困难且容易出错,因为其中有大量的选项。更有效和可靠的方法是使用命令行工具来查看和更新你需要更改的特定设置。这可以避免滚动浏览数百行,并防止意外错误。

首先,让我们检查我们需要修改的设置的当前值:listen_addresseswal_levelmax_wal_senders

CONF_FILE="/etc/postgresql/14/main/postgresql.conf"
echo "--- Current Settings ---"
sudo grep -E "^#?\s*(listen_addresses|wal_level|max_wal_senders)" $CONF_FILE

你可能会看到这些行被 # 注释掉了。

现在,让我们自动更新这些设置。以下命令将备份配置文件,然后更新每个必需的参数。

CONF_FILE="/etc/postgresql/14/main/postgresql.conf"
## 在进行更改前创建备份
sudo cp $CONF_FILE ${CONF_FILE}.bak.$(date +%s)

## 将 listen_addresses 设置为允许来自任何 IP 地址的连接
sudo sed -i -E "s/^[#\s]*listen_addresses\s*=.*/listen_addresses = '*'/" "$CONF_FILE"

## 将 wal_level 设置为 'replica' 以启用复制日志
sudo sed -i -E "s/^[#\s]*wal_level\s*=.*/wal_level = replica/" "$CONF_FILE"

## 设置并发复制连接的最大数量
sudo sed -i -E "s/^[#\s]*max_wal_senders\s*=.*/max_wal_senders = 10/" "$CONF_FILE"

最后,让我们验证更改是否已正确应用。下面的命令将显示更新后的值,并过滤掉任何注释行。

echo "--- Verified Settings ---"
sudo grep -E "^(listen_addresses|wal_level|max_wal_senders)" $CONF_FILE

输出应显示更新后的活动配置:

listen_addresses = '*'
wal_level = replica
max_wal_senders = 10

确认这些设置后,服务器已为后续步骤正确配置。

2. 创建专用复制用户

最佳实践是使用专用用户进行复制,而不是超级用户。让我们创建一个名为 replicator 的角色。

使用 psql 命令行客户端连接到 PostgreSQL:

sudo -u postgres psql

现在,运行以下 SQL 命令,为用户创建复制权限和密码:

CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD 'replicapass';

你应该会看到 CREATE ROLE 的输出。现在,退出 psql 客户端:

\q

3. 允许复制连接

接下来,你需要配置服务器以允许 replicator 用户从副本服务器进行连接。你将通过编辑 pg_hba.conf 文件来实现这一点。

使用 nano 打开文件:

sudo nano /etc/postgresql/14/main/pg_hba.conf

将以下行添加到文件末尾。此规则指定用户 replicator 被允许从任何 IP 地址 (0.0.0.0/0) 连接到 replication 伪数据库。在本实验中,我们使用 127.0.0.1/32,因为两个服务器都在同一台机器上。

host    replication     replicator      127.0.0.1/32            md5

Ctrl+X,然后按 Y,最后按 Enter 保存并退出。

4. 重启主服务器

要应用所有这些配置更改,你必须重启 PostgreSQL 服务。

sudo service postgresql restart

主服务器现在已准备好接受复制连接。

从基础备份创建副本

主服务器配置完成后,下一步是创建副本。标准方法是获取主服务器的“基础备份”。这会创建主服务器数据目录的一个精确副本,该副本将作为副本的起点。

1. 为副本创建数据目录

首先,创建一个新目录来存储副本的数据。最佳实践是将其创建在系统位置,而不是用户的家目录,以避免权限问题。我们将以 postgres 用户在 PostgreSQL 的标准目录中创建它。

sudo -u postgres mkdir -p /var/lib/postgresql/14/replica

2. 获取基础备份

现在,使用 pg_basebackup 工具从主服务器复制数据。此命令将以 replicator 用户身份连接到主服务器,并将数据流式传输到新的副本目录。由于你是以 postgres 用户创建的目录,因此没有权限问题需要解决。

运行以下命令。系统会提示你输入 replicator 用户的密码,即 replicapass

sudo -u postgres pg_basebackup -h localhost -p 5432 -U replicator -D /var/lib/postgresql/14/replica -P -v -R

让我们分解一下这个命令:

  • sudo -u postgres: 以 postgres 系统用户身份运行命令,该用户拥有必要的权限。
  • pg_basebackup: 用于获取基础备份的工具。
  • -h localhost -p 5432: 指定主服务器的主机和端口。
  • -U replicator: 用于连接的用户名。
  • -D /var/lib/postgresql/14/replica: 备份的目标目录。
  • -P: 显示进度报告。
  • -v: 启用详细模式。
  • -R: 这是一个非常有用的选项。它会创建一个 standby.signal 文件,并将连接设置追加到目标目录中的 postgresql.auto.conf 文件,从而自动将新数据目录配置为副本。

3. 复制配置文件

基础备份会复制主要数据文件,但在许多基于 Debian 的系统(如本 Ubuntu 环境)中,配置文件(pg_hba.confpg_ident.conf)单独存储在 /etc/postgresql/ 中,并且不包含在备份中。你必须手动将它们复制到副本的数据目录。复制后,还必须确保它们的所有者是 postgres 用户,以便服务器进程可以读取它们。

sudo cp /etc/postgresql/14/main/pg_hba.conf /var/lib/postgresql/14/replica/
sudo cp /etc/postgresql/14/main/pg_ident.conf /var/lib/postgresql/14/replica/
sudo chown postgres:postgres /var/lib/postgresql/14/replica/pg_hba.conf
sudo chown postgres:postgres /var/lib/postgresql/14/replica/pg_ident.conf

数据文件和配置就位后,副本目录已准备好进行最终配置步骤。

配置并启动副本服务器

基础备份已准备好副本的数据目录。但是,由于你将主服务器和副本服务器都运行在同一台机器上,它们不能同时使用相同的网络端口(默认是 5432)。在此步骤中,你将配置副本使用不同的端口,然后启动它。

1. 配置副本的端口

编辑副本数据目录中的 postgresql.conf 文件以更改其监听端口。请注意,你需要 sudo,因为此文件现在由 postgres 用户拥有。

sudo nano /var/lib/postgresql/14/replica/postgresql.conf

在文件末尾添加以下行,将端口设置为 5433

port = 5433

Ctrl+X,然后按 Y,最后按 Enter 保存并退出。

2. 设置数据目录权限

出于安全考虑,PostgreSQL 要求其数据目录不能被其他用户访问。你必须将其权限设置为 700,这仅授予所有者(postgres)读、写和执行权限。

sudo chmod 0700 /var/lib/postgresql/14/replica

3. 启动副本服务器

现在你可以启动副本服务器了。你将使用 pg_ctl,这是一个标准的 PostgreSQL 用于控制数据库服务器的实用程序。

运行以下命令来启动副本。你必须使用 pg_ctl 的完整路径,因为 sudo 命令可能不知道在哪里找到它。我们还将指定一个位于 /tmp 的日志文件,以便轻松检查服务器状态。

sudo -u postgres /usr/lib/postgresql/14/bin/pg_ctl -D /var/lib/postgresql/14/replica -l /tmp/replica.log start
  • pg_ctl: 服务器控制实用程序。
  • -D /var/lib/postgresql/14/replica: 指定此服务器实例的数据目录。
  • -l /tmp/replica.log: 指定日志文件。
  • start: 要执行的操作。

你应该会看到以下消息:

waiting for server to start.... done
server started

4. 检查副本的日志文件

为了确认副本已正确启动并连接到主服务器,请使用 sudo 查看其日志文件,因为该文件由 postgres 用户拥有:

sudo cat /tmp/replica.log

查找指示数据库系统已准备好接受只读连接并已开始从主服务器流式传输 WAL 的行。你应该会看到类似以下内容:

...
LOG:  database system is ready to accept read-only connections
LOG:  started streaming WAL from primary at 0/4000000 on timeline 1
...

这证实了你的副本服务器已启动、运行并成功连接到主服务器。

测试复制

现在两个服务器都已运行,是时候测试复制是否按预期工作了。你将在主服务器上创建一个表,并验证它是否出现在副本上。你还将确认副本是只读的。

1. 在主服务器上检查复制状态

首先,连接到主服务器(端口 5432)并检查 pg_stat_replication 视图。此视图提供了有关已连接副本的监控信息。

sudo -u postgres psql -p 5432

运行此查询:

SELECT client_addr, state, sync_state FROM pg_stat_replication;

输出应显示你的副本已连接,其状态为 streamingsync_stateasyncsync

 client_addr |   state   | sync_state
-------------+-----------+------------
 127.0.0.1   | streaming | async
(1 row)

2. 在主服务器上创建数据

在连接到主服务器时,创建一个新表并插入一些数据:

CREATE TABLE replication_test (id INT, message TEXT);
INSERT INTO replication_test VALUES (1, 'Hello from primary!');

现在,查询该表以确认数据已存在:

SELECT * FROM replication_test;

你应该会看到你刚刚插入的行。退出主服务器的 psql shell:

\q

3. 在副本上验证数据

打开一个新的终端或使用你现有的终端连接到副本服务器(端口 5433)。你需要提供 postgres 用户的密码,即 labex

psql -h localhost -p 5433 -U postgres -d postgres

现在,在副本上查询 replication_test 表:

SELECT * FROM replication_test;

你应该会看到与你在主服务器上创建的完全相同的数据。这证实了流复制正在工作!

 id |      message
----+---------------------
  1 | Hello from primary!
(1 row)

4. 测试副本的只读特性

尝试在副本上向表中插入数据:

INSERT INTO replication_test VALUES (2, 'Hello from replica?');

该命令将因错误而失败,因为副本服务器默认处于只读模式。

ERROR:  cannot execute INSERT in a read-only transaction

这是预期的行为,也是流副本的一个关键特征。退出副本的 psql shell:

\q

清理环境

在最后一步中,你将关闭服务器并删除在实验过程中创建的文件和目录,以将环境恢复到初始状态。

1. 停止副本服务器

首先,使用 pg_ctl 停止副本服务器。请记住使用可执行文件的完整路径。

sudo -u postgres /usr/lib/postgresql/14/bin/pg_ctl -D /var/lib/postgresql/14/replica stop

你将看到一条确认消息,表明服务器已停止。

waiting for server to shut down.... done
server stopped

2. 停止主服务器

接下来,使用 service 命令停止主服务器。

sudo service postgresql stop

3. 删除副本数据和日志

服务器已停止,现在你可以安全地删除副本的数据目录和你创建的日志文件。请注意,由于这些文件由 postgres 用户拥有,因此需要 sudo

sudo rm -rf /var/lib/postgresql/14/replica /tmp/replica.log

这完成了清理过程。你已成功设置、测试并拆除了一个 PostgreSQL 流复制环境。

总结

在此次实验中,你成功地从零开始配置了 PostgreSQL 流复制。你学会了如何通过修改 postgresql.confpg_hba.conf 文件以及创建一个专用的复制用户来准备主服务器。然后,你使用 pg_basebackup 创建了一个副本,并将其配置为在单独的端口上运行。

通过测试配置,你验证了写入主服务器的数据几乎实时地自动复制到辅助服务器。你还确认了副本服务器是只读的,这是其设计的一个基本方面。这些技能对于管理健壮且可扩展的 PostgreSQL 部署至关重要。