数据库修仙炼气篇九——postgresql流复制同异步分析

文章详细介绍了PostgreSQL流复制的过程,涉及backend进程、walsender、walreceiver和startup进程的角色。关键参数synchronous_commit控制事务同步模式,可设置为local、remote_write、remote_apply、on、off等。synchronous_standby_names则定义了同步备节点的数量和名称。当walsender接收到walreceiver的确认后,会根据配置判断是否满足同步要求,唤醒相应的backend进程以继续执行。

postgresql流复制同异步分析

postgresql流复制主要是四个进程的交互。

  • postgres(backend进程)(主节点)

    接受客户端的请求,并通过共享内存等待walsender唤醒。

  • walsender(主节点)

    向walreceiver发送日志,通过tcp通信,采用流复制协议与walreceiver交互。

  • walreceiver(备节点)

    向walsender请求日志,并回复wal日志接收,写入,数据apply信息,通过tcp通信,采用流复制协议与walsender通信。

  • startup(备节点)

    进行日志回放,将wal日志redo成数据,通过共享内存和信号与walreceiver通信。

参数

流复制同异步由如下两个参数控制:

  • synchronous_commit

    用于指定同异步模式。

  • synchronous_standby_names

    用于指定同步时需要多少备节点确认。

synchronous_commit

配置解析

{"synchronous_commit", PGC_USERSET, WAL_SETTINGS,
            gettext_noop("Sets the current transaction's synchronization level."),
            NULL
        },
        &synchronous_commit,
        SYNCHRONOUS_COMMIT_ON, synchronous_commit_options,
        NULL, assign_synchronous_commit, NULL
static const struct config_enum_entry synchronous_commit_options[] = {
    {"local", SYNCHRONOUS_COMMIT_LOCAL_FLUSH, false},
    {"remote_write", SYNCHRONOUS_COMMIT_REMOTE_WRITE, false},
    {"remote_apply", SYNCHRONOUS_COMMIT_REMOTE_APPLY, false},
    {"on", SYNCHRONOUS_COMMIT_ON, false},
    {"off", SYNCHRONOUS_COMMIT_OFF, false},
    {"true", SYNCHRONOUS_COMMIT_ON, true},
    {"false", SYNCHRONOUS_COMMIT_OFF, true},
    {"yes", SYNCHRONOUS_COMMIT_ON, true},
    {"no", SYNCHRONOUS_COMMIT_OFF, true},
    {"1", SYNCHRONOUS_COMMIT_ON, true},
    {"0", SYNCHRONOUS_COMMIT_OFF, true},
    {NULL, 0, false}
};

配置不同的值代表不同的同步模式。

synchronous_standby_names

配置解析

{
        {"synchronous_standby_names", PGC_SIGHUP, REPLICATION_PRIMARY,
            gettext_noop("Number of synchronous standbys and list of names of potential synchronous ones."),
            NULL,
            GUC_LIST_INPUT
        },
        &SyncRepStandbyNames,
        "",
        check_synchronous_standby_names, assign_synchronous_standby_names, NULL
    },
SyncRepConfig = (SyncRepConfigData *) extra;

在check_synchronous_standby_names中解析后最终将其赋值给了SyncRepConfig。

synchronous_standby_names可以配置为某个具体的备节点名,也可以配置成any 1(*)的形式。

synchronous_standby_names = 'standby001'

或者

synchronous_standby_names='ANY 1 (*)'

walsender进程处理同步

walsender收到walreceiver回复的r报文
唤醒满足条件的backend进程
计算备库的回复确认是否满足要求,同时会计算writePtr,flushPtr,applyPtr
获取候选者个数
SYNC_REP_PRIORITY优先级模式计算ptr,最旧的
非优先级模式计算ptr,第n个
ProcessStandbyMessage
ProcessStandbyReplyMessage
SyncRepReleaseWaiters
SyncRepGetSyncRecPtr
SyncRepGetCandidateStandbys
SyncRepGetOldestSyncRecPtr
SyncRepGetNthLatestSyncRecPtr

收到walreceiver的确认报文,walsender需要判断回复的standby个数是否满足配置的要求。SyncRepGetSyncRecPtr中会计算已经回复的standby个数并和配置的值进行比较,若满足则会返回true,否则返回false。

got_recptr = SyncRepGetSyncRecPtr(&writePtr, &flushPtr, &applyPtr, &am_sync);
    if (!got_recptr || !am_sync)	{ // 若确认的standby个数不足或者不是sync模式直接返回
		LWLockRelease(SyncRepLock);
		announce_next_takeover = !am_sync;
		return;
	}

若确认的standby个数不足或者不是sync模式直接返回;

若确认的standby个数满足,且是sync模式,则需要唤醒对应模式的backend进程。

    if (walsndctl->lsn[SYNC_REP_WAIT_WRITE] < writePtr)
	{
		walsndctl->lsn[SYNC_REP_WAIT_WRITE] = writePtr;
		numwrite = SyncRepWakeQueue(false, SYNC_REP_WAIT_WRITE);
	}
	if (walsndctl->lsn[SYNC_REP_WAIT_FLUSH] < flushPtr)
	{
		walsndctl->lsn[SYNC_REP_WAIT_FLUSH] = flushPtr;
		numflush = SyncRepWakeQueue(false, SYNC_REP_WAIT_FLUSH);
	}
	if (walsndctl->lsn[SYNC_REP_WAIT_APPLY] < applyPtr)
	{
		walsndctl->lsn[SYNC_REP_WAIT_APPLY] = applyPtr;
		numapply = SyncRepWakeQueue(false, SYNC_REP_WAIT_APPLY);
	}

此时唤醒对应的后端进程后,后端进程将回复客户端。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我在数据库世界里修仙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值