本文记录了如何在RHEL 7.6下搭建PostgreSQL 12.2的一主两备高可用集群。
一、方案比较
官网共列了8种方案,各有优缺点,详细可参考:
https://www.postgresql.org/docs/current/different-replication-solutions.html
图1.高可用方案比较
综合比较后,本文将选用流复制的同步方式搭建一主两备的高可用集群,主要优势有:主备强一致性、数据永不丢失、原生备份方式、轻量、读性能佳;主要缺点为只能主机执行写,且同步模式下需等待备机写完。因此,想要做读写分离,或者对于读性能要求高、写请求性能要求不那么高的场景,该方案是比较合适的。
流复制的主要原理
流复制是搭建主备库的一种有效方式,它不需要额外增加软件,只需要在单数据库模式的基础上,再复制一份PostgreSQL数据库到另外的一台机器上,对两台数据库进行参数配置,即可实现。
这两套数据库之间的数据,通过wal日志,后台自动同步。对外部的应用程序而言,可以看作是两套数据库,需要根据业务需要,显式分别连接不同的数据库。
PG主备流复制的核心部分由walsender,walreceiver和startup三个进程组成。
walsender进程是用来发送WAL日志记录的,执行顺序如下:
PostgresMain()->exec_replication_command()->StartReplication()->WalSndLoop()->XLogSendPhysical()
walreceiver进程是用来接收WAL日志记录的,执行顺序如下:
sigusr1_handler()->StartWalReceiver()->AuxiliaryProcessMain()->WalReceiverMain()->walrcv_receive()
startup进程是用来apply日志的,执行顺序如下:
PostmasterMain()->StartupDataBase()->AuxiliaryProcessMain()->StartupProcessMain()->StartupXLOG()
下图是PG主备总体框架图:
图2.PG主备总体框架图
walsender和walreceiver进程流复制过程
walsender和walreceiver交互主要分为以下几个步骤:
1、walreceiver启动后通过recovery.conf文件中的primary_conninfo参数信息连向主库,主库通过连接参数replication=true启动walsender进程;
2、walreceiver执行identify_system命令,获取主库systemid/timeline/xlogpos等信息,执行TIMELINE_HISTORY命令拉取history文件;
3、执行wal_startstreaming开始启动流复制,通过walrcv_receive获取WAL日志,期间也会回应主库发过来的心跳信息(接收位点、flush位点、apply位点),向主库发送feedback信息(最老的事务id),避免vacuum删掉备库正在使用的记录;
4、执行walrcv_endstreaming结束流复制,等待startup进程更新receiveStart和receiveStartTLI,一旦更新,重新进入2/3/4步骤。