流复制和逻辑复制的区别

79

有没有人能告诉我PostgreSQL中物理复制和逻辑复制的区别?

1个回答

176
TL;DR: 逻辑复制发送行级别更改,物理复制发送磁盘块更改。对于某些任务而言,逻辑复制更好,而对于其他任务而言,物理复制更好。

请注意,在PostgreSQL 12(当前版本)中,逻辑复制已经稳定可靠,但功能相当有限。如果您在询问此问题,请使用物理复制。


流式复制 可能是 逻辑复制。这有点复杂。

WAL-shipping vs streaming

在PostgreSQL中,有两种主要的将数据从主服务器发送到副本服务器的方式:

  • WAL-shipping连续归档(Continuous Archiving),其中单个预写日志文件从pg_xlog通过在主服务器上运行的archive_command被复制到另一个位置。 副本的recovery.conf中配置的restore_command在副本上运行以获取这些存档,以便副本可以重放WAL。

    这就是用作持续备份方法的时间点复制(Point-in-Time Replication)(PITR)所使用的方法。

    与主服务器之间不需要直接的网络连接。复制可能会有较长的延迟,特别是没有设置archive_timeout。WAL-shipping不能用于同步复制。

  • 流式复制(streaming replication),其中每个更改都会在发生时直接通过TCP/IP连接发送到一个或多个副本服务器。 副本必须在其recovery.confprimary_conninfo选项中配置与主服务器的直接网络连接。

    只要副本足够快以跟上,流式复制就几乎没有延迟。可以将其用于同步复制(Synchronous Replication)。您不能使用流式复制进行PITR1,因此对于持续备份没有什么用。如果在主服务器上删除表,则副本也会被删除。

因此,这两种方法具有不同的目的。但是,它们都传输物理WAL存档,仅在时间和WAL段是否在途中被存档的方式上有所不同。

通常应该结合使用这两种方法,通常使用流式复制,但启用archive_command。然后在副本上,设置restore_command以允许副本在主副之间存在直接连通性问题时从WAL存档中进行还原。

异步复制与同步复制

除此之外,还有同步(Synchronous)异步(Asynchronous)流式复制:

  • 在异步流式复制中,副本允许落后于主服务器的时间,当主服务器更快/更繁忙时。如果主服务器崩溃,则可能会丢失尚未复制的数据。

    如果异步副本落后于主服务器太远,当 max_wal_size(先前称为wal_keep_segments)过低且未使用插槽时,主服务器可能会丢弃副本所需的信息,这意味着您必须从头开始重新创建副本。或者如果 max_wal_size 设置过高或使用了插槽,则主服务器的pg_wal(先前为pg_xlog)可能会填满并停止工作,直到释放磁盘空间。
    同步复制中,主服务器在收到副本已确认接收到事务之前不会完成提交2。如果主服务器崩溃且您必须故障转移至副本,则永远不会丢失数据。主服务器永远不会丢弃副本所需的数据或填满其xlog,并因副本延迟而耗尽磁盘空间。代价是它可能会使主服务器变慢甚至停止工作,如果副本出现问题,则始终对主服务器产生一些性能影响,因为网络延迟的存在而导致。
    当有多个副本时,每次只有一个副本是同步的。请参见synchronous_standby_names
    您无法进行同步的日志传送。
    实际上,您可以将日志传送和异步复制结合起来以防止副本落后太远而必须重新创建副本,而不会影响主服务器。这是许多部署的理想配置,结合监视副本与主服务器之间的差距,以确保其在可接受的灾难恢复限制范围内。
    此外,在PostgreSQL 9.4中引入了逻辑物理流式复制:
    物理流式复制中,更改以几乎磁盘块级别发送,例如“在关系12311的磁盘页面18的偏移14处写入十六进制值为0x2342beef1222的元组...”。
    物理复制发送所有内容:PostgreSQL安装中每个数据库的内容、每个数据库中的所有表,它发送索引条目,当您执行VACUUM FULL时,它发送整个新的表数据,它发送回滚的事务的数据等等。因此它产生很多“噪音”并发送大量冗余数据。它还要求副本完全相同,因此您无法执行任何需要事务的操作,例如创建临时或未记录的表。在副本上查询会延迟复制,因此必须取消副本上的长查询。
    作为交换,应用更改于副本上非常简单且高效,并且副本与主服务器可靠地完全相同。DDL透明地复制,就像其他所有内容一样,因此不需要特殊处理。它还可以在大事务发生时即时流传输,因此对于大改动,在主服务器提交和副本提交之间几乎没有延迟。
    物理流式复制是成熟、经过充分测试并广泛采用的技术。
    • 逻辑流复制在9.4版本中推出,它以更高的层级和更精细地方式发送更改。

    它一次只复制一个数据库。它仅发送已提交的事务的行更改,并且不必发送vacuum数据、索引更改等。它可以选择性地仅向数据库内的某些表发送数据。这使得逻辑复制比物理复制更加节省带宽。

    在更高的层面上运行也意味着您可以在副本数据库上执行事务。您可以创建临时表和非记录表。即使是普通表也可以。您可以使用外部数据封装器、视图、创建函数等。如果查询运行时间过长也无需取消。

    逻辑复制还可用于在PostgreSQL中构建多主复制,这在物理复制中不可能。

    但换取的是,它(目前)无法实时流式传输大型事务,而必须等待它们提交。因此,主服务器上发布大型事务和副本应用它之间可能存在很长的延迟。

    它严格按照提交顺序回放事务,因此小型快速事务可能会被大型事务阻塞并延迟很长时间。

    DDL不会自动处理。您必须自己在主副本之间保持表定义同步,或者使用逻辑复制应用程序自己的设施来完成此操作。这可能很复杂。

    应用过程本身也比“按照指定位置写一些字节”更为复杂。它还需要比物理复制更多的副本资源。

    当前的逻辑复制实现并不成熟、普及或特别易于使用。

    选择太多了,请告诉我该怎么做

    哇。很复杂吧?我甚至还没涉及延迟复制、插槽、max_wal_size、时间线、如何执行晋升、Postgres-XL、BDR和多主等细节。

    那么你应该 什么呢?

    没有单一正确的答案。否则,PostgreSQL将只支持该方法。但是有一些常见用例:

    对于备份和灾难恢复,请使用pgbarman进行基本备份并保存WAL,提供易于管理的连续备份。您仍应定期进行pg_dump备份以获得额外的保险。

    对于零数据丢失风险的高可用性,请使用流同步复制。

    对于低数据丢失风险和更好的性能的高可用性,您应使用异步流复制。要么启用WAL归档以备用,要么使用复制插槽。使用外部工具(如Icinga)监控副本与主服务器之间的延迟。

    参考文献


2
@JoshuaBurns 我忙着开发,但是https://2ndquadrant.com的其他人确实会协助这样的设置。更一般地,可以访问https://www.postgresql.org/support/professional_support/。 - Craig Ringer
2
自从这个回答发布以来,逻辑复制已经取得了长足的进步。您对推荐有什么变化吗? - mlissner
1
@FranklinYu WAL 运输是物理的,即涉及原始 WAL 运输。 - Craig Ringer
4
@Awesome-o,如果使用了复制槽,则WAL日志会无限期保留。但是在PostgreSQL 13中,现在有一个max_slot_wal_keep_size选项,用于设置槽位WAL日志的保留限制。考虑到它是高级功能,您可能不需要它。还请注意,wal_keep_segments已被max_wal_size设置替换。 - Craig Ringer
1
@Abrißbirne66,“流式复制”和“使用archive_command和restore_command(日志传送)进行复制”是基于WAL存档的两种复制方式。它们都传输WAL存档,但它们的方式不同。它们可以组合使用,如果出现连接问题,Postgres将从一个切换到另一个。 - Craig Ringer
显示剩余11条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接