Opengauss主备机制介绍
工作原理
Opengauss以流复制的方式把WAL日志文件传到备库,备库接收到WAL日志后进行重放以达到数据同步的过程。
WAL日志由一系列的WAL记录(wal record)构成,每一个 wal record分配一个序列号lsn(log sequence number),顺序递增。
流复制传输的单位是wal record。
主备数据同步的过程中,主要涉及以下三个线程:
walsender线程 :负责向备库发送wal record
walreceiver线程 :负责接收主库的wal record
startup线程 :负责把wal日志文件apply为data数据
复制模式
分为同步复制和异步复制。
同步复制:
在流复制开始前,startup线程首先从本地归档或wal日志存放目录寻找是否有可回放的日志;
如果没有,备库开始建立流复制连接以从主库获取要回放的wal日志文件。
- 首先startup线程会向备库主进程发送信号,启动walreceiver线程。
- walreceiver向主库主进程发送请求启动walsender线程,随后walsender建立一条与walreceiver的TCP连接。
备库会向主库发送备库最新的record lsn。
(3)流复制建立连接后,客户端应用程序连接数据库开始向主库提交事务。
(4)walwriter线程把事务日志从缓存刷到磁盘。
(5)walsender线程读取wal日志文件逐个向备库发送wal record。
(6)备库的walreceiver线程接收来自主库的wal record,并用walrecwrite线程把这record刷到磁盘上形成wal文件。
(7)备库wal落地成文件后,startup线程开始进行回放。
同步复制中客户端需要等待备库返回的ACK消息,根据wal日志在备库的执行结果分为以下几个级别:
remote_receive :表示备库接收到了wal日志数据
remote_write :表示备库接收wal日志并刷到磁盘
remote_apply :表示备库接收wal日志并完成回放
(8)根据synchronous_commit设置的不同级别,备库的wal日志执行到相应的结果后,walreceiver线程会向walsender发送响应的ACK消息。
(9)walsender给postgres(在opengauss中是backend worker线程)发送消息释放latch锁,事务提交成功。
(10)postgres反馈给客户端事务提交成功的消息。
异步复制
异步复制过程中,主库客户端不必等待备库的ACK消息,待主库WAL日志落盘后,postgres就可以直接向客户端返回提交成功。
重点参数
synchronous_commit
synchronous_commit =off
采用异步复制。
synchronous_standby_names
潜在同步复制的备机名称列表,每个名称用逗号分隔。
synchronous_standby_names = 'ANY 1 (dn_6002,dn_6003)'
ANY num_sync (standby_name [, …]) [, ANY num_sync (standby_name [, …])]
[FIRST] num_sync (standby_name [, …])
standby_name [, …]
其中 num_sync 是事务需要等待其回复的同步复制的备机的数量,
standby_name 是备机的名称,
FIRST以及ANY指定从所列服务器中选取同步复制的备机的策略。
most_available_sync
most_available_sync=on
在有同步备机故障时,主机事务不因同步备机故障而被阻塞。
on表示在有同步备机故障时,不阻塞主机。
off表示在有同步备机故障时,阻塞主机。
wal_receiver_timeout
设置从主机接收数据的最大等待时间。
wal_receiver_connect_timeout
设置连接主机的最大等待超时时间。
wal_receiver_connect_retries
设置连接主机的最大尝试次数
replconninfo1
复制连接信息
replconninfo1 = 'localhost=10.1.62.110 localport=15401 localheartbeatport=15405 localservice=15404 remotehost=10.1.62.111 remoteport=15401 remoteheartbeatport=15405 remoteservice=15404'
# replication connection information used to connect primary on standby, or standby on primary, or connect primary or standby on secondary
# The heartbeat thread will not start if not set localheartbeatport and remoteheartbeatport.
Replconninfo2
replconninfo2 = 'localhost=10.1.62.110 localport=15401 localheartbeatport=15405 localservice=15404 remotehost=10.1.62.112 remoteport=15401 remoteheartbeatport=15405 remoteservice=15404'




