- 专栏内容:postgresql内核源码分析
- 个人主页:我的主页
- 座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.
目录
前言
介绍
数据结构
WAL对端的状态
walsender进程
WALsender交互流程
在握手阶段,主要做了两件事情:
在握手交互后,开始真正开始wal传送,调用关系如下:
walsend进程流程
结尾
前言
本文是基于postgresql 15的代码进行分析解读,演示是在centos8系统上进行。
介绍
walsender 看名字就知道,它是通过tcp协议发送write ahead log。
那么它是什么场景下使用呢?
以及如何获得wal产生的呢?
如何与对应协调呢?
下面我们就来看看。
数据结构
typedef struct WalSnd
{
pid_t pid; /* this walsender's PID, or 0 if not active */
WalSndState state; /* this walsender's state */
XLogRecPtr sentPtr; /* WAL has been sent up to this point */
bool needreload; /* does currently-open file need to be
* reloaded? */
/*
* The xlog locations that have been written, flushed, and applied by
* standby-side. These may be invalid if the standby-side has not offered
* values yet.
*/
XLogRecPtr write;
XLogRecPtr flush;
XLogRecPtr apply;
/* Measured lag times, or -1 for unknown/none. */
TimeOffset writeLag;
TimeOffset flushLag;
TimeOffset applyLag;
/*
* The priority order of the standby managed by this WALSender, as listed
* in synchronous_standby_names, or 0 if not-listed.
*/
int sync_standby_priority;
/* Protects shared variables in this structure. */
slock_t mutex;
/*
* Pointer to the walsender's latch. Used by backends to wake up this
* walsender when it has work to do. NULL if the walsender isn't active.
*/
Latch *latch;
/*
* Timestamp of the last message received from standby.
*/
TimestampTz replyTime;
ReplicationKind kind;
} WalSnd;
这是walsender上下文的记录,记录了walsender进程pid, 以及wal发送的记录位置等。
WAL对端的状态
WAL记录,有三种状态,记录了接收端的WAL处理情况;
writed, WAL已经接收被写入磁盘;
flush, WAL被刷到磁盘上;因为先是写到缓存中,接收一部分后统计调用flush。
apply, WAL日已经在备机被回放应用了;
walsender进程
启动方式与backend一样,在postmaster收到replication的连接后启动一个backend,这个backend不处理SQL,只处理replication相关的命令。
其中对于physicalreplication,也就是流复制,主要就是发送wal。几种场景下都会启动walsender,一是在pg_basebackup时,通过walsender发送数据拷贝和wal;二是在热备时,主节点向备节点发送wal;三是级联的备节点时,上级备节点向下级备节点wal;
WALsender交互流程
在walsender启动之后,walsender与walreceiver需要进行握手交互,交互流程如下:
(1)备->walsender "IDENTIFY_SYSTEM"
walsender->备 回复
(2)备->walsender "START_REPLICATION 6/4A000000 TIMELINE 3"
T_StartReplicationCmd
(3)walsender查找 historytimeline找到对应的切换lsn,如果请求的startlsn还在,就按请求的位置发送;
-
在握手阶段,主要做了两件事情:
(1)确认主机版本;
(2)协商WAL发送的起始位置;备机请求的lsn,在主机上是否存在,如果是过期的,WAL已经不存在了或者还没产生,那就流复制失败;
-
在握手交互后,开始真正开始wal传送,调用关系如下:
exec_replication_command
->IdentifySystem
->StartReplication
->WalSndLoop
-
walsend进程流程
walsender在流复制过程中,一直会在WalSndLoop循环,大概流程如下:
(1)发送WAL调用XLogSendPhysical,从wal文件里直接读取数据;
每次最大可以发送16倍的xlog block;
#define MAX_SEND_SIZE (XLOG_BLCKSZ * 16)
当然这个大小可以与walreceiver进行协商,来控制流量;
(2)当前没有可发的WAL时,调用WalSndWait进行等待;如果网络阻塞也会在此等待事件;
(3)空闲时会发送keepalive消息;
(4)事件等待,在XlogWrite时通过WalSndWakeupRequest()打开walsender通知开关,说明已经有WAL写入磁盘;当有WAL刷盘完成后,在XLogFlush中通过WalSndWakeupProcessRequests通知walsender进行发送;
结尾
作者邮箱:study@senllang.onaliyun.com
如有错误或者疏漏欢迎指出,互相学习。
注:未经同意,不得转载!