PG15 pg_basebackup 代码解析

news2024/11/17 21:43:36

背景

先前 PG 版本 pg_basebackup 的代码较为复杂,pg_basebackup 在备份过程中做了很多事情,但这部分代码逻辑没有完全解耦,导致一个文件里包含了很多功能的逻辑,影响了代码的可读性和可修改性。

因此,PG 15 针对这部分代码做了一个重构,在保证提供的功能没有发生变化的前提下,完成了模块间的解耦。

本文将针对重构这部分代码进行解析,建议先阅读下面 背景知识介绍 对应的文章。

  • 背景知识介绍:PostgreSQL物理备份内部原理
  • pg_basebackup 文档:https://www.postgresql.org/docs/15/app-pgbasebackup.html
  • 社区重构 commit:https://github.com/postgres/postgres/commit/23a1c6578c87fca0e361c4f5f9a07df5ae1f9858
  • 本文 PG 代码版本:15.1

整体架构

PG 15 的 pg_basebackup 部分采用 管道-过滤器 风格(数据流风格的一种),引入 bbstreamer 这个抽象结构,所有的过滤器都是 bbstreamer 的扩展。
举一个简单的例子,使用下述语句将 server 端的数据进行备份,并将输出重定向到标准输出。

pg_basebackup -h localhost -U postgres -p 5432  -Xf -Ft -D- 

那么,整个数据流的处理如下图所示
在这里插入图片描述
执行 pg_basebackup 后,server 端会发送若干个 tar 包给 pg_basebackup 对应的进程,对于每一个 tar 包,pg_basebackup 进程都将其视作数据流处理,并让数据流经过若干个过滤器进行处理:

  1. bbstreamer_tar_parser:负责解析 server 端发来的 tar 文件,并将处理后的数据流向下一个过滤器;
  2. bbstreamer_tar_archiver: 负责组装 tar 包操作,对数据进行进一步处理并将其流向下一个过滤器;
  3. bbstreamer_tar_file:负责最终的文件写入操作,将数据流写入指定的文件中。

代码分析

bbstreamer 结构分析

bbstreamer 结构的详细内容参考 bbstreamer.h 文件,里面解释非常全面。这里介绍两个主要结构体

struct bbstreamer
{
	const bbstreamer_ops *bbs_ops; /* 当前 bbstreamer 结构的函数指针 */
	bbstreamer *bbs_next; /* 指向下一个 bbstreamer 结构 */
	StringInfoData bbs_buffer; /* 临时 buffer */
};

struct bbstreamer_ops
{
	/* 函数指针:实现 bbstreamer 过滤器需要针对数据流的具体操作 */
	void		(*content) (bbstreamer *streamer, bbstreamer_member *member,
							const char *data, int len,
							bbstreamer_archive_context context);

	/* 函数指针:bbstreamer 清理函数 */
	void		(*finalize) (bbstreamer *streamer);
	void		(*free) (bbstreamer *streamer);
};

用面向对象的角度来看,bbstreamer 结构体可以看成基类,上文说的类似 bbstreamer_tar_parser 都可以看成它的子类,尤其扩展而来,并实现 bbstreamer_ops 里的三个函数。

处理流程

筛选出 pg_basebackup 中的关键函数后,整体的函数流程图如下所示

  1. 用户使用 pg_basebackup 后,经过初始化处理进入 BaseBackup 函数;
  2. 如果 server 端为 PG 15 版本,调用 ReceiveArchieveStream 函数接收数据流;
  3. ReceiveCopyData 函数循环接收数据,并调用回调函数 ReceiveArchieveStreamChunk 进行处理;
  4. ReceiveArchieveStreamChunk 函数负责一系列 bbstreamer 结构的初始化,以及使用 bbstreamer 结构体进行后续处理;
  5. 处理完毕后,针对各 streamer 进行清理操作;

对于第 4 步,我们还是使用之前的例子来做具体分析

pg_basebackup -h localhost -U postgres -p 5432  -Xf -Ft -D- 

其入口函数就是下面这个 bbstreamer_content 函数,该函数会调用当前 bbstreamer 对应实现的 content 函数。

/* Send some content to a bbstreamer. */
static inline void
bbstreamer_content(bbstreamer *streamer, bbstreamer_member *member,
				   const char *data, int len,
				   bbstreamer_archive_context context)
{
	Assert(streamer != NULL);
	streamer->bbs_ops->content(streamer, member, data, len, context);
}

对于上面的 pg_basebackup 命令,当到了最后一个过滤器 bbstreamer_plain_writer 时,会将内容写到 base.tar 中,此时的函数堆栈如下

(gdb) bt
#0  bbstreamer_plain_writer_content ()
    at bbstreamer_file.c:110
#1  0x0000000000409c94 in bbstreamer_content ()
    at bbstreamer.h:131
#2  0x000000000040a774 in bbstreamer_tar_archiver_content ()
    at bbstreamer_tar.c:437
#3  0x0000000000409c94 in bbstreamer_content ()
    at bbstreamer.h:131
#4  0x000000000040a47d in bbstreamer_tar_header ()
    at bbstreamer_tar.c:310
#5  0x0000000000409f5f in bbstreamer_tar_parser_content ()
    at bbstreamer_tar.c:142
#6  0x0000000000403607 in bbstreamer_content ()
    at bbstreamer.h:131
#7  0x0000000000405de8 in ReceiveArchiveStreamChunk ()
    at pg_basebackup.c:1449
    
下面省略若干行上层函数堆栈

可以看到,对于三个过滤器,每个过滤器执行完当前 bbstreamer 对应的函数后,都会继续调用下一个过滤器对应的 bbstreamer 函数,直到 bbstreamer_plain_writer_content 完成写 tar 文件,不再递归调用。

总结

PG 15 针对 pg_basebackup 这部分的重构,较好的完成了模块间的解耦。如果需要针对数据流做额外的修改操作,只需要按照其设计模式新增一个过滤器即可。例如不想直接写 tar 文件,想使用 gzip 额外进行压缩,只需要将最后的 bbstreamer_plain_writer 换成 bbstreamer_gzip_writer 即可。开发者在熟悉了这一架构后,可以非常快的进行开发。

参考资料

[1] http://mysql.taobao.org/monthly/2018/08/06/
[2] https://www.postgresql.org/docs/15/app-pgbasebackup.html
[3] https://github.com/postgres/postgres/commit/23a1c6578c87fca0e361c4f5f9a07df5ae1f9858

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/186059.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

模电学习3. 差模、共模干扰与安规电容

模电学习3. 差模、共模干扰与安规电容一、简介1. 安规2. 电源安规标准二、差模干扰与共模干扰1. 共模干扰2. 差模干扰(1)定义(2)来源与特性3. 测量4. 消除电源线路中的差模干扰(1)差模电容5. 消除电源线路中…

TOOM加强网络舆情监控制定处置预案,抓好舆情监控管理?

舆情预案是指根据对未来舆情发展趋势的预测,制定预先准备的舆情处置方案,以应对可能出现的舆情危机。舆情预案包括舆情预警体系、舆情应对策略、应对措施等内容,旨在在舆情危机发生前进行有效的预防和准备,避免舆情危机扩大&#…

95. BERT预训练数据代码

为了预训练之前实现的BERT模型,我们需要以理想的格式生成数据集,以便于两个预训练任务:遮蔽语言模型和下一句预测。一方面,最初的BERT模型是在两个庞大的图书语料库和英语维基百科的合集上预训练的,但它很难吸引这本书…

Zookeeper 教程

Zookeeper 教程Zookeeper 概述分布式应用Zookeeper 架构图ZooKeeper当中的主从与主备:Zookeeper的特性分布式应用的优点分布式应用的挑战什么是Apache ZooKeeper?ZooKeeper的好处Zookeeper 基础ZooKeeper的架构层次命名空间Znode的类型Sessions&#xff…

九龙证券|外资放大招,400亿巨头狂飙!这只翻倍股却突然崩了

昨日超级“开门红”之后,今天上午港股又有多只重磅个股大幅涨超10%。 今日上午,港股整体窄幅震荡,上午收盘,恒生指数微跌0.05%,恒生科技指数涨0.22%。 职业板块方面,媒体、软件服务、电信等涨幅居前&#…

【BLE】ANCS(Apple Notification Center Service)

目录1. 前言1.1 名词解释1.2 ANCS概述2. ANCS的特征2.1 通知源2.2 控制点和数据源2.3 获取通知属性2.4 获取应用属性2.5 执行通知操作2.6 通知操作3. 更多详情参考1. 前言 1.1 名词解释 NP(Notification Provider):消息提供者,指的是ANCS服务的生产者&…

【JavaSE】入门概述(1~41)

1.Java视频及配套资料下载指南 2.Java基础学习导读 Java语言的三个层面 基本语法:变量、运算符、流程控制、数组面向对象:把数据及对数据的操作方法放在一起,作为一个相互依存的整体——对象高级应用:多线程、集合、IO流、网络…

性能怪兽-Nginx常用配置指北

目录 安装 Nginx操作命令 https反向代理 负载均衡 轮询 加权轮询 最少连接 加权最少连接 IP Hash 普通 Hash 动静分离 资源压缩 缓冲区 缓存机制 解决跨域 防盗链设计 配置SLL证书 性能优化 打开长连接配置 开启零拷贝技术 开启无延迟或多包共发机制 调整W…

Python连接Liunx中mysql数据库-增删改查

上一篇文章已经讲解了如何连接liunx中的mysql数据库,如果没有连接好数据库的话,可以看这一篇文章 增删改查Mysql中查询操作1.创建游标2.定义一个sql的查询语句3.调用游标内的sql语句执行操作4.打印出查询结果5.完整代码6.指定查询Mysql中新增操作1.单条数…

jupyter 常用记录

安装windows环境下 运行cmd 然后:在命令提示窗口输入pip install jupyter,然后回车;完成后运行 jupyter notebook 前言 提起jupyter notebook,应该很多学习过Python的同学都不陌生。虽然用jupyter notebook的同学相对较少,但是提…

Java多级缓存是为了解决什么的?

前言 提到缓存,想必每一位软件工程师都不陌生,它是目前架构设计中提高性能最直接的方式。 缓存技术存在于应用场景的方方面面。从网站提高性能的角度分析,缓存可以放在浏览器,可以放在反向代理服务器,还可以放在应用…

使用JINJA2模板部署自定义文件(RH294)

在ansible中有许多模板可以用于修改现有的文件比如—— lineinfile和blockinfile但是!我们还有一种更加便捷而且牛皮的方法为其构建模板在部署该文件是自动为受管主机自定义次模板配置文件而这些模板中非常有名的就是 JINJA2ansible将Jinja2模板系统用于模板文件 并…

Java设计模式-职责链模式Chain of Responsibility

介绍 职责链模式(Chain of Responsibility Pattern), 又叫 责任链模式,为请求创建了一个接收者对象的链(简单示意图)。这种模式对请求的发送者和接收者进行解耦。职责链模式通常每个接收者都包含对另一个接收者的引用。如果一个对象不能处理…

C语言#include的用法详解

#include叫做文件包含命令,用来引入对应的头文件(.h文件)。#include 也是C语言预处理命令的一种。#include 的处理过程很简单,就是将头文件的内容插入到该命令所在的位置,从而把头文件和当前源文件连接成一个源文件&am…

Oracle数据库故障处理-存储单块读hang分析处理

1 故障描述 2023年1月27日下午接到业务反馈数据库存在大量的锁表阻塞信息,并且业务的页面以及数据库的一些查询均处于阻塞状态,简单的查询sql也需要查询很长时间且未返回结果,数据库hang状态。 2 故障原因分析 2.1 数据库层面分析 接到业务反馈后&am…

如果放在几年前,无法想到互联网会蜕变成今天这样一副模样

如果放在几年前,你是万万无法想到互联网会蜕变成今天这样一副模样。尽管如此,这样一种蜕变却在真实地发生着。不知道你有没有发现就连前两年火爆的短视频人们都懒得刷了。所有的这一切都在告诉我们,互联网正在发生一场深刻而又彻底的嬗变。如…

SQL Server数据库版本总结

一、为什么要写这篇文章 之所以专门写一篇文章来整理归纳SQL Server各个版本的功能区别,是因为遇到过两次真实的客户案例,因为数据库版本选取不当,导致生产系统宕机的情况。 案例一 某客户安装了 32位 版本的SQL Server 2008 R2 数据库&…

人工智能轨道交通行业周刊-第31期(2023.1.16-1.29)

本期关键词:磁悬浮原理、小米石、通信铁塔维护、桥隧工巡检、地方铁路十大新闻 1 整理涉及公众号名单 1.1 行业类 RT轨道交通中关村轨道交通产业服务平台人民铁道世界轨道交通资讯网铁路信号技术交流北京铁路轨道交通网上榜铁路视点ITS World轨道交通联盟VSTR铁路…

element 日期组件实现只能选择小时或者只能选择小时、分钟

前言 在使用 element 框架时,总是会有一些满足不了现有项目需求的问题,这个时候就需要我们对 element 的组件进行改造,最近有一个需求就是要求日期组件只能选择年月日时,不要分钟和秒,找了一圈,发现 elemen…

【Markdown】CSDN 的 Markdown 编辑器锚点使用-进阶篇

1. 原始 Markdown 代码 1.1 “目录”元素 [TOC](8.6 InnoDB ClusterSet 的状态和拓扑)1.2 “1号标题-1”元素 # InnoDB ClusterSet 状态1.3 “1号标题-2”元素 <h1> <a id"innodb-clusterset-topology">InnoDB ClusterSet 拓扑</a> </h1>…