共享磁盘故障转移避免了同步开销,因为只有一个数据库副本。它使用一个由多个服务器共享的单一磁盘阵列。如果主数据库服务器发生故障,备用服务器能够像从数据库崩溃中恢复一样挂载并启动数据库。这允许快速故障转移而不会丢失数据。
共享硬件功能在网络存储设备中很常见。使用网络文件系统也是可能的,尽管必须注意文件系统具有完整的POSIX行为(参见第 18.2.2.1 节)。此方法的一个主要限制是,如果共享磁盘阵列发生故障或损坏,主服务器和备用服务器都将无法运行。另一个问题是,在主服务器运行时,备用服务器永远不应访问共享存储。
共享硬件功能的一个修改版本是文件系统复制,其中文件系统的所有更改都会镜像到另一台计算机上的文件系统中。唯一的限制是,镜像必须以确保备用服务器拥有文件系统的Consistent副本的方式完成——特别是,必须按照与主服务器相同的顺序在备用服务器上执行写操作。DRBD是Linux上流行的文件系统复制解决方案。
可以通过读取预写日志(WAL)记录流来使温备和热备服务器保持最新。如果主服务器发生故障,备用服务器将包含主服务器的几乎所有数据,并可以快速成为新的主数据库服务器。这可以是同步的或异步的,并且只能用于整个数据库服务器。
可以使用基于文件的日志传输(第 26.2 节)或流复制(参见第 26.2.5 节),或两者的组合来实现备用服务器。有关热备的信息,请参见第 26.4 节。
逻辑复制允许数据库服务器将数据修改流发送到另一台服务器。PostgreSQL逻辑复制从WAL构建逻辑数据修改流。逻辑复制允许按表复制数据更改。此外,发布自身更改的服务器也可以订阅另一台服务器的更改,从而允许数据双向流动。有关逻辑复制的更多信息,请参见第 29 章。通过逻辑解码接口(第 47 章),第三方扩展也可以提供类似功能。
基于触发器的复制设置通常将数据修改查询定向到指定的服务器。基于表进行操作,主服务器(通常)异步地将数据更改发送到备用服务器。在主服务器运行时,备用服务器可以响应查询,并且可能允许一些本地数据更改或写入活动。这种复制形式通常用于分载大型分析或数据仓库查询。
Slony-I是此类复制的一个示例,具有按表粒度和多备用服务器支持。因为它异步地(分批)更新备用服务器,所以在故障转移期间可能丢失数据。
使用基于SQL的复制中间件,程序会拦截每个SQL查询并将其发送到一个或所有服务器。每个服务器独立运行。读写查询必须发送到所有服务器,以便每个服务器接收任何更改。但只读查询可以仅发送到一个服务器,从而允许在它们之间分配读取工作负载。
如果查询只是未经修改地广播,则random()
、CURRENT_TIMESTAMP
和序列等函数在不同服务器上可能会有不同的值。这是因为每个服务器独立运行,并且因为SQL查询是广播的而不是实际的数据更改。如果这是不可接受的,则中间件或应用程序必须从单个源确定这些值,然后将这些值用于写入查询。还必须注意,所有事务要么在所有服务器上提交,要么中止,可能使用两阶段提交(PREPARE TRANSACTION和COMMIT PREPARED)。Pgpool-II和Continuent Tungsten是此类复制的示例。
对于不经常连接或通信链接缓慢的服务器,如笔记本电脑或远程服务器,保持服务器之间的数据一致性是一项挑战。使用异步多主复制,每个服务器独立工作,并定期与其他服务器通信以识别冲突事务。冲突可以通过用户或冲突解决规则来解决。Bucardo是此类复制的一个示例。
在同步多主复制中,每个服务器都可以接受写请求,并在每次事务提交之前,将修改后的数据从原始服务器传输到每个其他服务器。繁重的写操作可能导致过多的锁定和提交延迟,从而导致性能下降。读取请求可以发送到任何服务器。一些实现使用共享磁盘来减少通信开销。同步多主复制最适合以读取为主的工作负载,尽管它最大的优点是任何服务器都可以接受写请求——无需在主服务器和备用服务器之间划分工作负载,并且由于数据更改是从一个服务器发送到另一个服务器,因此不会出现random()
等非确定性函数的问题。
PostgreSQL不提供此类复制,尽管PostgreSQL两阶段提交(PREPARE TRANSACTION和COMMIT PREPARED)可以在应用程序代码或中间件中实现此功能。
表 26.1总结了上述各种解决方案的功能。
表 26.1. 高可用性、负载均衡和复制功能矩阵
功能 | 共享磁盘 | 文件系统复制 | 预写日志传输 | 逻辑复制 | 基于触发器的复制 | SQL复制中间件 | 异步MM复制 | 同步MM复制 |
---|---|---|---|---|---|---|---|---|
流行示例 | NAS | DRBD | 内置流复制 | 内置逻辑复制,pglogical | Londiste,Slony | pgpool-II | Bucardo | |
通信方法 | 共享磁盘 | 磁盘块 | WAL | 逻辑解码 | 表行 | SQL | 表行 | 表行和行锁 |
无需特殊硬件 | • | • | • | • | • | • | • | |
允许多个主服务器 | • | • | • | • | ||||
对主服务器无开销 | • | • | • | • | ||||
无需等待多个服务器 | • | (异步时) | (异步时) | • | • | |||
主服务器故障永不丢失数据 | • | • | (同步时) | (同步时) | • | • | ||
副本接受只读查询 | (热备时) | • | • | • | • | • | ||
按表粒度 | • | • | • | • | ||||
无需冲突解决 | • | • | • | • | • | • |
有几种解决方案不符合上述类别
数据分区将表分成数据集。每个数据集只能由一个服务器修改。例如,数据可以按办公室分区,例如伦敦和巴黎,每个办公室都有一个服务器。如果需要组合伦敦和巴黎数据的查询,应用程序可以查询两个服务器,或者可以使用主/备复制来在每个服务器上保留其他办公室数据的只读副本。
上述许多解决方案允许多个服务器处理多个查询,但没有一个允许单个查询使用多个服务器来更快地完成。此解决方案允许多个服务器同时处理单个查询。它通常通过将数据分布在服务器之间,并让每个服务器执行其查询部分,然后将结果返回到一个中央服务器,然后将它们合并并返回给用户来实现。可以使用PL/Proxy工具集实现这一点。
还应注意,由于PostgreSQL是开源的并且易于扩展,因此许多公司采用了PostgreSQL并创建了具有独特故障转移、复制和负载均衡功能的商业闭源解决方案。此处不讨论这些。
如果您在文档中看到任何不正确、与您对特定功能的体验不符或需要进一步解释的内容,请使用此表单报告文档问题。