本节描述了存在多个备库时,流复制是如何工作的。
11.3.1 同步优先级与同步状态
主库为自己管理的每一个备库指定一个同步优先级(sync_priority
) 与 同步状态(sync_state
) 。(上一节并没有提到这一点,即使主库只管理一个备库,也会指定这些值)。
同步优先级(sync_priority) 表示备库在同步模式下的优先级,它是一个固定值。较小的值表示较高的优先级,而0
是一个特殊值,表示“异步模式”。备库优先级是一个有序列表,在主库配置参数 synchronous_standby_names
中依序给出。例如在以下配置中,standby1
和standby2
的优先级分别为1和2。
synchronous_standby_names = 'standby1, standby2'
(未列于此参数中的备库处于异步模式,优先级为0)
同步状态(sync_state) 是备库的状态,它因所有在列备库的运行状态及其优先级而异,以下是可能的状态:
- 同步(Sync) 状态的备库,是所有正在工作中的备库中,具有最高优先级的同步备库的状态(异步模式除外)。
- 潜在(Potential) 状态的备库,是所有工作备库(异步备库除外)中,优先级等于或低于2的闲置同步备库。如果同步备库失效,潜在备库中有着最高优先级的那个将替换为同步备库。
- 异步(Async) 状态的备库是固定的。主库以与潜在备库相同的方式处理异步备库,只是它们的
sync_state
永远不会是sync
或potential
。
执行以下查询来显示备库的优先级和状态:
testdb=# SELECT application_name AS host,
sync_priority, sync_state FROM pg_stat_replication;
host | sync_priority | sync_state
----------+---------------+------------
standby1 | 1 | sync
standby2 | 2 | potential
(2 rows)
最近有几个开发者尝试实现“多个同步备库”。详情参见此处。
11.3.2 主库如何管理多个备库
主库仅等待来自同步备库的ACK响应。换句话说,主库仅确保同步备库写入并刷新WAL数据。因此在流复制中,只有同步备库的状态是与主库始终一致且同步的。
图11.3展示了潜在备库的ACK响应早于首要备库ACK响应的情况。这时主库并不会完成当前事务的COMMIT
操作,而是继续等待首要备库的ACK响应。而当收到首要备库的响应时,后端进程释放锁存器并完成当前事务的处理。
图11.3 管理多个备库
备库1与备库2的同步状态分别为
sync
和potential
。
- 尽管从潜在备库接收到ACK响应,但主库的后端进程会继续等待来自同步备库的ACK响应。
- 主库的后端进程释放锁存器,完成当前的事务处理。
在相反的情况下(即首要从库的ACK响应返回早于潜在从库的响应),主库会立即完成当前事务的COMMIT
操作,而不会去确认潜在从库是否已经写入和刷盘了WAL数据。
11.3.3 发生故障时的行为
我们再来看看当从库发生故障时主库的表现。
当潜在或异步备库发生故障时,主库会终止连接到故障备库的walsender 进程,并继续进行所有处理。换而言之,主库上的事务处理不会受到这两种备库的影响。
当同步备库发生故障时,主库将终止连接到故障备库的walsender 进程,并使用具有最高优先级的潜在备库替换首要同步备库,如图11.4。与上述的故障相反,主库将会暂停从失效点到成功替换同步备库之间的查询处理。(因此备库的故障检测对于提高复制系统可用性至关重要,故障检测将在下一节介绍)
图11.4 更换同步备库
在任何情况下,如果一个或多个备库在同步模式下运行,主库始终只会保留一个同步备库,而同步备库始终与主库保持一致且同步的状态。
下一节:流复制使用两种常见的故障检测过程,不需要任何特别的硬件。