27.1. 不同方案的比较

共享磁盘故障转移

共享磁盘故障转移避免了只使用一份数据库拷贝带来的同步开销。它使用一个由多个服务器共享的单一磁盘阵列。如果主数据库服务器失效,后备服务器则可以挂载并启动数据库,就好像它从一次数据库崩溃中恢复过来了。这是一种快速的故障转移,并且不存在数据丢失。

共享硬件功能在网络存储设备中很常见。也可以使用一个网络文件系统,但是要注意的是该文件系统应具有完全的POSIX行为(见第 19.2.2.1 节)。这种方法的一个重大限制是如果共享磁盘阵列失效或损坏,主要和后备服务器都会变得无法工作。另一个问题是在主要服务器运行时,后备服务器永远不能访问共享存储。

文件系统(块设备)复制

共享硬件功能的一种修改版本是文件系统复制,在其中对一个文件系统的所有改变会被镜像到位于另一台计算机上的一个文件系统。唯一的限制是该镜像过程必须能保证后备服务器有一份该文件系统的一致的拷贝 — 特别是对后备服务器的写入必须按照主控机上相同的顺序进行。DRBD是用于 Linux 的一种流行的文件系统复制方案。

预写式日志传送

温备和热备服务器能够通过读取一个预写式日志(WAL)记录的流来保持为当前状态。如果主服务器失效,后备服务器拥有主服务器的几乎所有数据,并且能够快速地被变成新的主数据库服务器。这可以是同步的或异步的,并且只能用于整个数据库服务器。

可以使用基于文件的日志传送(第 27.2 节)、流复制(见第 27.2.5 节)或两者的组合来实现一个后备服务器。关于热备的信息可见第 27.4 节

逻辑复制

逻辑复制允许数据库服务器发送数据更新流给另一台服务器。PostgreSQL逻辑复制从WAL构建出逻辑数据更新流。逻辑复制允许您逐个表复制数据更改。此外,发布数据更新的服务器可以同时订阅其他服务器的更改,从而允许数据在多个方向流动。有关逻辑复制的更多信息,请参考 第 31 章。通过逻辑解码接口 (第 49 章),第三方扩展也能提供类似的功能。

基于触发器的主-备复制

基于触发器的复制通常会将修改数据的查询发送到指定的主服务器。它在逐个表的基础上工作,主服务器(通常)将数据更改异步发送到备用服务器。 主服务器运行时,备用服务器可以响应查询,并执行本地数据修改或写入操作。这种形式的复制通常用于减轻大数据分析型平台或者数据仓库查询负荷。

Slony-I是这种复制类型的一个例子。它使用表粒度,并且支持多个后备服务器。因为它会异步更新后备服务器(批量),在故障转移时可能会有数据丢失。

基于SQL的复制中间件

通过基于SQL的复制中间件,一个程序拦截每一个 SQL 查询并把它发送给一个或所有服务器。每一个服务器独立地操作。读写查询必须被发送给所有服务器,这样每一个服务器都能接收到任何修改。但只读查询可以被只发送给一个服务器,这样允许读负载在服务器之间分布。

如果查询未经修改发送,则函数的random()随机值和CURRENT_TIMESTAMP函数的当前时间和序列值可能因不同服务器而异。 因为每个服务器独立运行,并且它发送 SQL 查询而没有真正的更改数据。如果这是不可接受的,那么中间件或应用程序必须从单一服务器源确定此类值,并将结果用于写入查询。 还必须注意确保所有服务器在提交或中止事务时都是相同的。这将涉及使用 两阶段提交(PREPARE TRANSACTIONCOMMIT PREPARED )。 Pgpool-IIContinuent Tungsten就是这种复制的例子。

异步多主控机复制

对于不会被定期连接或通讯链路较慢的服务器,如笔记本或远程服务器,保持服务器间的数据一致是一个挑战。通过使用异步的多主控机复制,每一个服务器独立工作并且定期与其他服务器通信来确定冲突的事务。这些冲突可以由用户或冲突解决规则来解决。Bucardo 是这种复制类型的一个例子。

同步多主控机复制

在同步多主控机复制中,每一个服务器能够接受写请求,并且在每一个事务提交之前,被修改的数据会被从原始服务器传送给每一个其他服务器。繁重的写活动可能导致过多的锁定和提交延迟,进而导致很差的性能。读请求可以被发送给任意服务器。某些实现使用共享磁盘来减少通信负荷。同步多主控机复制主要对于读负载最好,尽管它的大优点是任意服务器都能接受写请求 — 没有必要在主服务器和后备服务器之间划分负载,并且因为数据修改被从一个服务器发送到另一个服务器,不会有非确定函数(如random())的问题。

PostgreSQL不提供这种复制类型,尽管在应用代码或中间件中可以使用PostgreSQL的两阶段提交(PREPARE TRANSACTIONCOMMIT PREPARED)来实现这种复制。

表 27.1总结了上述多种方案的能力。

表 27.1. 高可用、负载均衡和复制特性矩阵

特性共享磁盘文件系统复制预写式日志传送逻辑复制基于触发器的复制SQL复制中间件异步多主控机复制同步多主控机复制
常用的示例NASDRBD内建流复制内建逻辑复制,pglogicalLondiste,Slonypgpool-IIBucardo 
通信方法共享磁盘磁盘块WAL逻辑解码表行SQL表行表行和行锁
不要求特殊硬件 
允许多个主控机服务器    
无主服务器负载    
不等待多个服务器 with sync offwith sync off  
主控机失效将永不丢失数据with sync onwith sync on  
复制体接受只读查询  with hot
每个表粒度    
不需要冲突解决  

有一些方案不适合上述的类别:

数据分区

数据分区将表分开成数据集。每个集合只能被一个服务器修改。例如,数据可以根据办公室划分,如伦敦和巴黎,每一个办公室有一个服务器。如果查询有必要组合伦敦和巴黎的数据,一个应用可以查询两个服务器,或者可以使用主/备复制来在每一台服务器上保持其他办公室数据的一个只读拷贝。

多服务器并行查询执行

上述的很多方案允许多个服务器来处理多个查询,但是没有一个允许一个单一查询使用多个服务器来更快完成。 这种方案允许多个服务器在一个单一查询上并发工作。 这通常通过把数据在服务器之间划分并且让每一个服务器执行该查询中属于它的部分,然后将结果返回给一个中心服务器,由它整合结果并发回给用户。 这也可以使用PL/Proxy工具集来实现这种方案。

还需要注意的是由于PostgreSQL是开源的并且易于扩展,许多公司已经采用PostgreSQL并创建了具有独特的故障转移、复制和负载平衡功能的商业闭源解决方案。这里不讨论这些。