PostgreSQL 复制:综合指南
已发表: 2022-08-11正如任何网站所有者都会告诉您的那样,数据丢失和停机时间,即使是最小的剂量,也可能是灾难性的。 他们可以随时打击措手不及的人,从而导致生产力、可访问性和产品信心降低。
为了保护您的站点的完整性,构建防止停机或数据丢失可能性的保护措施至关重要。
这就是数据复制的用武之地。
数据复制是一个自动备份过程,在该过程中,您的数据会从其主数据库重复复制到另一个远程位置以进行安全保护。 对于任何运行数据库服务器的站点或应用程序来说,它都是一项不可或缺的技术。 您还可以利用复制的数据库来处理只读 SQL,从而允许在系统内运行更多进程。
在两个数据库之间设置复制提供了针对意外事故的容错能力。 它被认为是在灾难期间实现高可用性的最佳策略。
在本文中,我们将深入探讨后端开发人员可以为无缝 PostgreSQL 复制实施的不同策略。
什么是 PostgreSQL 复制?
PostgreSQL 复制被定义为将数据从 PostgreSQL 数据库服务器复制到另一台服务器的过程。 源数据库服务器也称为“主”服务器,而接收复制数据的数据库服务器称为“副本”服务器。
PostgreSQL 数据库遵循简单的复制模型,其中所有写入都转到主节点。 然后主节点可以应用这些更改并将它们广播到辅助节点。
什么是自动故障转移?
一旦在 PostgreSQL 中配置了物理流复制,如果数据库的主服务器发生故障,就会发生故障转移。 故障转移用于定义恢复过程,这可能需要一段时间,因为它不提供用于确定服务器故障范围的内置工具。
您不必依赖 PostgreSQL 进行故障转移。 有专用工具允许自动故障转移和自动切换到备用数据库,从而减少数据库停机时间。
通过设置故障转移复制,您几乎可以通过确保在主服务器崩溃时备用服务器可用来保证高可用性。
使用 PostgreSQL 复制的好处
以下是利用 PostgreSQL 复制的几个主要好处:
- 数据迁移:您可以通过更改数据库服务器硬件或通过系统部署利用 PostgreSQL 复制进行数据迁移。
- 容错:如果主服务器发生故障,备用服务器可以充当服务器,因为主服务器和备用服务器包含的数据相同。
- 在线事务处理 (OLTP) 性能:您可以通过消除报告查询负载来提高 OLTP 系统的事务处理时间和查询时间。 事务处理时间是在事务完成之前执行给定查询所需的持续时间。
- 并行系统测试:升级新系统时,您需要确保系统能够很好地处理现有数据,因此需要在部署之前使用生产数据库副本进行测试。
PostgreSQL 复制的工作原理
通常,人们认为,当您涉足主要和次要架构时,只有一种方法可以设置备份和复制,但 PostgreSQL 部署遵循以下三种方法之一:
- 卷级复制,在存储层从主节点复制到辅助节点,然后将其备份到 Blob/S3 存储。
- PostgreSQL 流复制将数据从主节点复制到辅助节点,然后将其备份到 blob/S3 存储。
- 从主节点到 S3进行增量备份,同时从 S3 重建新的辅助节点。 当辅助节点在主节点附近时,您可以从主节点开始流式传输。
方法 1:流式传输
在所有服务器上安装 PostgreSQL 后,可以无缝设置 PostgreSQL 流复制也称为 WAL 复制。 这种复制方法基于将 WAL 文件从主数据库移动到目标数据库。
您可以使用主从配置来实现 PostgreSQL 流式复制。 主服务器是处理主数据库及其所有操作的主要实例。 辅助服务器充当补充实例,并在其自身上执行对主数据库所做的所有更改,并在此过程中生成相同的副本。 主服务器是读/写服务器,而辅助服务器只是只读的。
对于这种方法,您需要同时配置主节点和备用节点。 以下部分将阐明轻松配置它们所涉及的步骤。
配置主节点
您可以通过执行以下步骤来配置主节点以进行流式复制:
第 1 步:初始化数据库
要初始化数据库,您可以利用initidb utility
命令。 接下来,您可以使用以下命令创建具有复制权限的新用户:
CREATE USER REPLICATION LOGIN ENCRYPTED PASSWORD '';
用户必须为给定的查询提供密码和用户名。 replication 关键字用于为用户提供所需的权限。 示例查询如下所示:
CREATE USER rep_user REPLICATION LOGIN ENCRYPTED PASSWORD 'rep_pass'
步骤 2:配置流媒体属性
接下来,您可以使用 PostgreSQL 配置文件 ( postgresql.conf ) 配置流属性,该文件可以修改如下:
wal_level = logical wal_log_hints = on max_wal_senders = 8 max_wal_size = 1GB hot_standby = on
以下是上一个片段中使用的参数的一些背景知识:
-
wal_log_hints
:当备用服务器与主服务器不同步时,pg_rewind
功能需要此参数。 -
wal_level
:您可以使用此参数来启用 PostgreSQL 流式复制,可能的值包括minimal
、replica
或logical
。 -
max_wal_size
:这可用于指定可以保留在日志文件中的 WAL 文件的大小。 -
hot_standby
:当它设置为 ON 时,您可以利用此参数与辅助节点建立读取连接。 -
max_wal_senders
:您可以使用max_wal_senders
指定可以与备用服务器建立的最大并发连接数。
第 3 步:创建新条目
修改 postgresql.conf 文件中的参数后, pg_hba.conf文件中的新复制条目可以允许服务器相互建立连接以进行复制。
您通常可以在 PostgreSQL 的数据目录中找到该文件。 您可以使用以下代码片段:
host replication rep_user IPaddress md5
执行代码片段后,主服务器允许名为rep_user
的用户连接并充当备用服务器,方法是使用指定的 IP 进行复制。 例如:
host replication rep_user 192.168.0.22/32 md5
配置备用节点
要为流复制配置备用节点,请执行以下步骤:
步骤 1:备份主节点
要配置备用节点,请利用pg_basebackup
实用程序生成主节点的备份。 这将作为备用节点的起点。 您可以使用以下语法使用此实用程序:
pg_basebackp -D -h -X stream -c fast -U rep_user -W
上述语法中使用的参数如下:
-
-h
:您可以使用它来提及主要主机。 -
-D
:此参数表示您当前正在处理的目录。 -
-C
:您可以使用它来设置检查点。 -
-X
:此参数可用于包含必要的事务日志文件。 -
-W
:您可以使用此参数在链接到数据库之前提示用户输入密码。
步骤 2:设置复制配置文件
接下来,您需要检查复制配置文件是否存在。 如果没有,您可以将复制配置文件生成为 recovery.conf。
您应该在 PostgreSQL 安装的数据目录中创建此文件。 您可以使用pg_basebackup
实用程序中的-R
选项自动生成它。
recovery.conf文件应包含以下命令:
待机模式 = '开'
primary_conninfo = 'host=<master_host> port=<postgres_port> user=<replication_user> password=<password> application_name=”host_name”'
recovery_target_timeline = '最新的'
上述命令中使用的参数如下:
-
primary_conninfo
:您可以使用它通过利用连接字符串在主服务器和辅助服务器之间建立连接。 -
standby_mode
:此参数可以使主服务器在打开时作为备用服务器启动。 -
recovery_target_timeline
:您可以使用它来设置恢复时间。
要建立连接,您需要提供用户名、IP 地址和密码作为 primary_conninfo 参数的值。 例如:
primary_conninfo = 'host=192.168.0.26 port=5432 user=rep_user password=rep_pass'
步骤 3:重新启动辅助服务器
最后,您可以重新启动辅助服务器以完成配置过程。
但是,流式复制带来了一些挑战,例如:
- 各种 PostgreSQL 客户端(用不同的编程语言编写)与单个端点进行通信。 当主节点出现故障时,这些客户端将继续重试相同的 DNS 或 IP 名称。 这使得故障转移对应用程序可见。
- PostgreSQL 复制没有内置故障转移和监控功能。 当主节点发生故障时,您需要将辅助节点提升为新的主节点。 此提升需要以客户端仅写入一个主节点的方式执行,并且他们不会观察到数据不一致。
- PostgreSQL 复制它的整个状态。 当你需要开发一个新的从节点时,从节点需要从主节点回顾整个状态变化的历史,这是资源密集型的,并且使得消除头部节点并创建新节点的成本很高。
方法二:复制块设备
复制块设备方法依赖于磁盘镜像(也称为卷复制)。 在这种方法中,更改被写入持久卷,该卷被同步镜像到另一个卷。
这种方法的额外好处是它在云环境中与所有关系数据库(包括 PostgreSQL、MySQL 和 SQL Server 等)的兼容性和数据持久性。
但是,PostgreSQL 复制的磁盘镜像方法需要您复制 WAL 日志和表数据。 由于现在对数据库的每次写入都需要通过网络同步进行,因此您不能丢失一个字节,因为这可能会使您的数据库处于损坏状态。
这种方法通常使用 Azure PostgreSQL 和 Amazon RDS。
方法三:WAL
WAL 由段文件组成(默认为 16 MB)。 每个段都有一个或多个记录。 日志序列记录 (LSN) 是指向 WAL 中记录的指针,让您知道记录在日志文件中保存的位置/位置。
备用服务器利用 WAL 段(在 PostgreSQL 术语中也称为 XLOGS)来不断复制其主服务器的更改。 您可以使用预写日志记录来授予 DBMS 中的持久性和原子性,方法是在将字节数组数据块(每个都有一个唯一的 LSN)序列化到稳定存储之前,然后再将它们应用于数据库。
将突变应用于数据库可能会导致各种文件系统操作。 出现的一个相关问题是数据库如何在文件系统更新过程中由于断电而导致服务器故障的情况下确保原子性。 当数据库启动时,它会开始一个启动或重放过程,该过程可以读取可用的 WAL 段并将它们与存储在每个数据页上的 LSN 进行比较(每个数据页都标记有影响该页的最新 WAL 记录的 LSN)。
基于日志传送的复制(块级)
流式复制改进了日志传送过程。 与等待 WAL 切换相反,记录在创建时发送,从而减少复制延迟。
流复制还胜过日志传送,因为备用服务器通过利用复制协议通过网络与主服务器链接。 然后,主服务器可以直接通过此连接发送 WAL 记录,而无需依赖最终用户提供的脚本。
基于日志传送的复制(文件级)
日志传送定义为将日志文件复制到另一个 PostgreSQL 服务器以通过重放 WAL 文件来生成另一个备用服务器。 该服务器被配置为在恢复模式下工作,其唯一目的是应用任何出现的新 WAL 文件。
然后,此辅助服务器将成为主 PostgreSQL 服务器的热备份。 它还可以配置为只读副本,它可以提供只读查询,也称为热备用。
连续 WAL 归档
在创建 WAL 文件时将它们复制到pg_wal
子目录以外的任何位置以归档它们称为 WAL 归档。 每次创建 WAL 文件时,PostgreSQL 都会调用用户提供的脚本进行归档。
该脚本可以利用scp
命令将文件复制到一个或多个位置,例如 NFS 挂载。 归档后,可以利用 WAL 段文件在任何给定时间点恢复数据库。
其他基于日志的配置包括:
- 同步复制:在每个同步复制事务被提交之前,主服务器等待直到备用服务器确认他们获得了数据。 这种配置的好处是不会因为并行写入过程而引起任何冲突。
- 同步多主复制:在这里,每个服务器都可以接受写入请求,并且在每个事务提交之前,将修改的数据从原始服务器传输到每个其他服务器。 它利用 2PC 协议并遵守全有或全无规则。
WAL 流协议详细信息
在备用服务器上运行的称为 WAL 接收器的进程利用recovery.conf的primary_conninfo
参数中提供的连接详细信息,并通过利用 TCP/IP 连接连接到主服务器。
要开始流式复制,前端可以在启动消息中发送复制参数。 布尔值 true、yes、1 或 ON 让后端知道它需要进入物理复制 walsender 模式。
WAL sender 是另一个在主服务器上运行的进程,负责在 WAL 记录生成时将其发送到备用服务器。 WAL 接收器将 WAL 记录保存在 WAL 中,就好像它们是由本地连接的客户端的客户端活动创建的一样。
一旦 WAL 记录到达 WAL 段文件,备用服务器会不断地重播 WAL,以便主服务器和备用服务器是最新的。
PostgreSQL 复制的元素
在本节中,您将深入了解PostgreSQL复制的常用模型(单主和多主复制)、类型(物理和逻辑复制)和模式(同步和异步)。
PostgreSQL 数据库复制的模型
可扩展性是指在现有节点上增加更多的资源/硬件,以增强数据库存储和处理更多数据的能力,可以横向和纵向实现。 PostgreSQL 复制是水平可伸缩性的一个例子,它比垂直可伸缩性更难实现。 我们主要通过单主复制(SMR)和多主复制(MMR)来实现横向扩展。
单主复制允许仅在单个节点上修改数据,并将这些修改复制到一个或多个节点。 副本数据库中的复制表不允许接受任何更改,除了来自主服务器的更改。 即使他们这样做了,更改也不会复制回主服务器。
大多数时候,SMR 对应用程序来说已经足够了,因为它的配置和管理不太复杂,而且没有冲突的机会。 单主复制也是单向的,因为复制数据主要沿一个方向流动,从主数据库到副本数据库。
在某些情况下,仅 SMR 可能还不够,您可能需要实施 MMR。 MMR 允许多个节点充当主节点。 对多个指定主数据库中表行的更改将复制到每个其他主数据库中的对应表。 在这个模型中,经常使用冲突解决方案来避免重复主键等问题。
使用 MMR 有几个优点,即:
- 在主机故障的情况下,其他主机仍然可以提供更新和插入服务。
- 主节点分布在几个不同的位置,因此所有主节点发生故障的机会非常小。
- 能够使用主要数据库的广域网 (WAN),该数据库在地理位置上可以靠近客户端组,同时保持整个网络的数据一致性。
然而,实施 MMR 的缺点是复杂性和解决冲突的难度。
一些分支和应用程序提供了 MMR 解决方案,因为 PostgreSQL 本身并不支持它。 这些解决方案可能是开源的、免费的或付费的。 一种这样的扩展是双向复制 (BDR),它是异步的并且基于 PostgreSQL 逻辑解码功能。
由于 BDR 应用程序在其他节点上重放事务,如果正在应用的事务与在接收节点上提交的事务之间存在冲突,则重放操作可能会失败。
PostgreSQL 复制的类型
PostgreSQL 复制有两种类型:逻辑复制和物理复制。
一个简单的逻辑操作“initdb”将执行为集群创建基本目录的物理操作。 同样,一个简单的逻辑操作“CREATE DATABASE”将执行在基本目录中创建子目录的物理操作。
物理复制通常处理文件和目录。 它不知道这些文件和目录代表什么。 这些方法用于维护单个集群的全部数据的完整副本,通常在另一台机器上,并且在文件系统级别或磁盘级别完成,并使用确切的块地址。
逻辑复制是一种复制数据实体及其修改的方法,基于它们的复制身份(通常是主键)。 与物理复制不同,它处理数据库、表和 DML 操作,并在数据库集群级别完成。 它使用发布和订阅模型,其中一个或多个订阅者订阅发布者节点上的一个或多个发布。
复制过程首先对发布者数据库上的数据进行快照,然后将其复制到订阅者。 订阅者从他们订阅的发布中提取数据,并且可以稍后重新发布数据以允许级联复制或更复杂的配置。 订阅者以与发布者相同的顺序应用数据,从而保证单个订阅中发布的事务一致性,也称为事务复制。
逻辑复制的典型用例是:
- 将单个数据库(或数据库子集)中的增量更改发送给订阅者。
- 在多个数据库之间共享数据库的一个子集。
- 当单个更改到达订阅者时触发它们的触发。
- 将多个数据库合并为一个。
- 向不同的用户组提供对复制数据的访问。
订阅者数据库的行为方式与任何其他 PostgreSQL 实例相同,并且可以通过定义其发布来用作其他数据库的发布者。
当订阅者被应用程序视为只读时,单个订阅不会发生冲突。 另一方面,如果应用程序或其他订阅者对同一组表进行了其他写入,则可能会出现冲突。
PostgreSQL 同时支持这两种机制。 逻辑复制允许对数据复制和安全性进行细粒度控制。
复制模式
PostgreSQL复制主要有两种模式:同步和异步。 同步复制允许数据同时写入主服务器和从服务器,而异步复制确保数据先写入主机,然后再复制到从服务器。
在同步模式复制中,仅当这些更改已复制到所有副本时,主数据库上的事务才被视为完成。 副本服务器必须始终可用,以便在主服务器上完成事务。 同步复制模式用于具有即时故障转移要求的高端事务环境。
在异步模式下,当仅在主服务器上完成更改时,可以声明主服务器上的事务完成。 然后这些更改会在稍后的时间复制到副本中。 副本服务器可以在一定时间内保持不同步,称为复制滞后。 在崩溃的情况下,可能会发生数据丢失,但异步复制提供的开销很小,因此在大多数情况下是可以接受的(它不会使主机负担过重)。 从主数据库故障转移到辅助数据库的时间比同步复制要长。
如何设置 PostgreSQL 复制
在本节中,我们将演示如何在 Linux 操作系统上设置 PostgreSQL 复制过程。 在本例中,我们将使用 Ubuntu 18.04 LTS 和 PostgreSQL 10。
让我们深入挖掘!
安装
您将首先通过以下步骤在 Linux 上安装 PostgreSQL:
- 首先,您必须通过在终端中键入以下命令来导入 PostgreSQL 签名密钥:
wget -q https://www.postgresql.org/media/keys/ACCC4CF8.asc -O- | sudo apt-key add -
- 然后,通过在终端中键入以下命令来添加 PostgreSQL 存储库:
echo "deb http://apt.postgresql.org/pub/repos/apt/ bionic-pgdg main" | sudo tee /etc/apt/sources.list.d/postgresql.list
- 通过在终端中键入以下命令来更新存储库索引:
sudo apt-get update
- 使用 apt 命令安装 PostgreSQL 包:
sudo apt-get install -y postgresql-10
- 最后,使用以下命令设置 PostgreSQL 用户的密码:
sudo passwd postgres
在开始 PostgreSQL 复制过程之前,主服务器和辅助服务器都必须安装 PostgreSQL。
为两台服务器设置 PostgreSQL 后,您可以继续进行主服务器和辅助服务器的复制设置。
在主服务器中设置复制
在主服务器和辅助服务器上安装 PostgreSQL 后执行这些步骤。
- 首先,使用以下命令登录 PostgreSQL 数据库:
su - postgres
- 使用以下命令创建复制用户:
psql -c "CREATEUSER replication REPLICATION LOGIN CONNECTION LIMIT 1 ENCRYPTED PASSWORD'YOUR_PASSWORD';"
- 在 Ubuntu 中使用任何 nano 应用程序编辑pg_hba.cnf并添加以下配置:文件编辑命令
nano /etc/postgresql/10/main/pg_hba.conf
要配置文件,请使用以下命令:
host replication replication MasterIP/24 md5
- 打开并编辑 postgresql.conf 并将以下配置放入主服务器:
nano /etc/postgresql/10/main/postgresql.conf
使用以下配置设置:
listen_addresses = 'localhost,MasterIP'
wal_level = replica
wal_keep_segments = 64
max_wal_senders = 10
- 最后,在主主服务器中重新启动 PostgreSQL:
systemctl restart postgresql
您现在已经完成了主服务器中的设置。
在辅助服务器中设置复制
按照以下步骤在辅助服务器中设置复制:
- 使用以下命令登录 PostgreSQL RDMS:
su - postgres
- 停止 PostgreSQL 服务的工作以使我们能够使用以下命令对其进行处理:
systemctl stop postgresql
- 使用此命令编辑pg_hba.conf文件并添加以下配置:
编辑命令nano /etc/postgresql/10/main/pg_hba.conf
配置
host replication replication MasterIP/24 md5
- 在辅助服务器中打开并编辑postgresql.conf并放置以下配置或取消注释(如果已注释):编辑命令
配置nano /etc/postgresql/10/main/postgresql.conf
listen_addresses = 'localhost,SecondaryIP'
wal_keep_segments = 64
wal_level = replica
hot_standby = on
max_wal_senders = 10
SecondaryIP 是从服务器的地址
- 访问辅助服务器中的 PostgreSQL 数据目录并删除所有内容:
cd /var/lib/postgresql/10/main
rm -rfv *
- 将 PostgreSQL 主服务器数据目录文件复制到 PostgreSQL 辅助服务器数据目录,并在辅助服务器中写入此命令:
pg_basebackup -h MasterIP -D /var/lib/postgresql/11/main/ -P -U
replication --wal-method=fetch
- 输入主服务器 PostgreSQL 密码并回车。 接下来,为恢复配置添加以下命令:编辑命令
nano /var/lib/postgresql/10/main/recovery.conf
配置
standby_mode = 'on' primary_conninfo = 'host=MasterIP port=5432 user=replication password=YOUR_PASSWORD' trigger_file = '/tmp/MasterNow'
这里,YOUR_PASSWORD 是 PostgreSQL 创建的主服务器中复制用户的密码
- 设置密码后,您必须重新启动辅助 PostgreSQL 数据库,因为它已停止:
systemctl start postgresql
测试您的设置
现在我们已经执行了这些步骤,让我们测试复制过程并观察辅助服务器数据库。 为此,我们在主服务器中创建一个表,并观察它是否反映在辅助服务器上。
让我们开始吧。
- 由于我们在主服务器中创建表,您需要登录到主服务器:
su - postgres psql
- 现在我们创建一个名为“testtable”的简单表,并通过在终端中运行以下 PostgreSQL 查询将数据插入到表中:
CREATE TABLE testtable (websites varchar(100)); INSERT INTO testtable VALUES ('section.com'); INSERT INTO testtable VALUES ('google.com'); INSERT INTO testtable VALUES ('github.com');
- 登录从服务器观察从服务器PostgreSQL数据库:
su - postgres psql
- 现在,我们检查表 'testtable' 是否存在,并且可以通过在终端中运行以下 PostgreSQL 查询来返回数据。 该命令实质上显示了整个表格。
select * from testtable;
这是测试表的输出:
| websites | ------------------- | section.com | | google.com | | github.com | --------------------
您应该能够观察到与主服务器中的数据相同的数据。
如果您看到以上内容,那么您已经成功进行了复制过程!
PostgreSQL 手动故障转移步骤是什么?
让我们回顾一下 PostgreSQL 手动故障转移的步骤:
- 使主服务器崩溃。
- 通过在备用服务器上运行以下命令来提升备用服务器:
./pg_ctl promote -D ../sb_data/ server promoting
- 连接到提升的备用服务器并插入一行:
-bash-4.2$ ./edb-psql -p 5432 edb Password: psql.bin (10.7) Type "help" for help. edb=# insert into abc values (4,'Four');
如果插入工作正常,则备用服务器(以前是只读服务器)已升级为新的主服务器。
如何在 PostgreSQL 中自动进行故障转移
设置自动故障转移很容易。
您将需要 EDB PostgreSQL 故障转移管理器 (EFM)。 在每个主节点和备用节点上下载并安装 EFM 后,您可以创建一个 EFM 集群,该集群由一个主节点、一个或多个备用节点以及一个在发生故障时确认断言的可选见证节点组成。
EFM 持续监控系统运行状况并根据系统事件发送电子邮件警报。 当发生故障时,它会自动切换到最新的备用服务器并重新配置所有其他备用服务器以识别新的主节点。
它还重新配置负载平衡器(例如 pgPool)并防止“裂脑”(当两个节点都认为它们是主节点时)发生。
概括
由于数据量大,可伸缩性和安全性已成为数据库管理中最重要的两个标准,尤其是在事务环境中。 虽然我们可以通过向现有节点添加更多资源/硬件来纵向提高可扩展性,但这并不总是可行的,通常是由于添加新硬件的成本或限制。
因此,需要水平可扩展性,这意味着向现有网络节点添加更多节点,而不是增强现有节点的功能。 这就是 PostgreSQL 复制出现的地方。
在本文中,我们讨论了 PostgreSQL 复制的类型、优势、复制模式、安装以及 SMR 和 MMR 之间的 PostgreSQL 故障转移。 现在让我们听听你的意见。
你通常实现哪一个? 哪个数据库功能对您来说最重要,为什么? 我们很乐意阅读您的想法! 在下面的评论部分分享它们。