暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

PolarDB PostgreSQL版VFS模块介绍

PolarDB 2025-01-09
218

关于 PolarDB PostgreSQL 版

PolarDB PostgreSQL 版是一款阿里云自主研发的云原生关系型数据库产品,100% 兼容 PostgreSQL,高度兼容Oracle语法;采用基于 Shared-Storage 的存储计算分离架构,具有极致弹性、毫秒级延迟、HTAP 、Ganos全空间数据处理能力和高可靠、高可用、弹性扩展等企业级数据库特性。同时,PolarDB PostgreSQL 版具有大规模并行计算能力,可以应对 OLTP 与 OLAP 混合负载。

VFS模块原理

Linux内核中,使用VFS模块抽象文件系统一致的行为,并提供统一的上层文件I/O调用接口,屏蔽掉底层不同文件系统具体的实现,因此,其可以灵活的加载/卸载多种不同的文件系统。

PolarDB PostgreSQL版是基于 Shared-Storage 的存储计算分离架构,也需要适配底层不同的 Shared-Storage 实现,为了达到和Linux内核一样灵活的适配不同的共享存储文件系统,PolarDB PostgreSQL提出了PolarDB VFS(PolarDB Virtual File System)模块,其大体架构如下图所示。

image.png

PolarDB VFS模块针对上层其他模块传入的I/O操作进行了分类处理,将I/O操作交给对应的文件系统实现接口进行处理。分类的依据是文件路径,一个具体的文件路径只对应一个具体的文件系统,不允许出现一个文件路径对应多个文件系统的现象。

PolarDB VFS模块目前支持三种具体的文件系统实现:PolarDB File System文件系统、本地Direct I/O文件系统、本地Buffer I/O文件系统。在此架构下,PolarDB VFS模块可以灵活地添加/删除底层不同的文件系统实现,并且还可以在VFS模块中对I/O操作执行不同粒度的监控。

VFS模块实现

路径协议

在前述章节“PolarDB PostgreSQL版手动部署与共享存储配置介绍”中,提到了PoalrDB PostgreSQL使用参数polar_datadir配置共享存储的路径,该参数的格式为:polar_datadir=[protocol://]path。

PolarDB PostgreSQL借鉴了URL的格式,对polar_datadir路径进行了类似的划分,分为protocol和path两部分,其中protocol就是对底层不同文件系统实现的标识,支持三类:“pfsd://”、“file-dio://”、“file://”,分别对应PolarDB File System文件系统、本地Direct I/O文件系统、本地Buffer I/O文件系统。对于每个具体路径协议的内部实现原理,将会在接下来的文章中介绍。

一个文件的I/O操作,最开始传入的参数都是路径,因为路径中包含protocol字段,因此,可以确定其对应的具体文件系统实现,即使后期如read、write等I/O操作不再需要文件路径,但由于PolarDB VFS模块中已经缓存了句柄fd对应的具体文件系统实现类别,因此,仍然可以将read、write等I/O操作交给正确的文件系统实现接口去处理。

FD缓存

根据上述内容可以得知,部分I/O操作函数是不带有路径的,因为只根据路径协议是无法辨别对应的文件系统实现类别。另外,由于不同的文件系统实现可能会同时被PolarDB PostgreSQL其他模块调用,而且不同的文件系统实现接口对于不同路径的文件,其返回的句柄fd有可能是相同的。

为了避免上述两个问题带来的影响,PolarDB VFS模块需要提供一层FD缓存来屏蔽底层不同文件系统的具体实现,其大体架构如下图所示:

image.png

FD缓存向上提供统一的VFS fd,其内部维护VFS fd与PFSD fd、DIO fd、BIO fd之间的映射关系,其维护映射关系使用的数据结构是一个空闲VFS fd链表,将空闲的VFS fd放到链表中维护,分配时从空闲链表头中取出第一个即可。链表的每一个VFS fd元素的结构及介绍如下:

typedef struct vfs_vfd
{

 int    fd; /* 对应的PFSD fd、DIO fd或者BIO fd的具体值 */
 int    kind; /* 对应的文件系统实现类别:PFSD、DIO或者BIO */
 int    type; /* 文件所属的类型,PolarDB PostgreSQL将文件按照其用途划分了几个类型,比如:数据、事务、WAL日志等,主要用于监控 */
 int    next_free; /* 下一个空闲VFS fd元素位置 */
 char   *file_name; /* 文件路径 */
} vfs_vfd;

I/O操作函数

为了方便将文件I/O操作函数进行管理,以及兼容不同文件系统实现类别的I/O操作函数,PolarDB VFS模块需要一个文件I/O操作函数的集合,于是定义了vfs_mgr结构体,如下所示,将open、read、write等I/O操作函数汇聚到该结构体中。

typedef struct vfs_mgr
{

int (*vfs_env_init)(void);
int (*vfs_env_destroy)(void);
int (*vfs_mount)(void);
int (*vfs_remount)(void);
int (*vfs_open)(constchar *path, int flags, mode_t mode);
int (*vfs_creat)(constchar *path, mode_t mode);
int (*vfs_close)(int fd);
ssize_t (*vfs_read)(int fd, void *buf, size_t len);
ssize_t (*vfs_write)(int fd, constvoid *buf, size_t len);
ssize_t (*vfs_pread)(int fd, void *buf, size_t len, off_t offset);
ssize_t (*vfs_pwrite)(int fd, constvoid *buf, size_t len, off_t offset);
int (*vfs_stat)(constchar *path, struct stat *buf);
int (*vfs_fstat)(int fd, struct stat *buf);
int (*vfs_lstat)(constchar *path, struct stat *buf);
off_t (*vfs_lseek)(int fd, off_t offset, int whence);
off_t (*vfs_lseek_cache)(int fd, off_t offset, int whence);
int (*vfs_access)(constchar *path, int mode);
int (*vfs_fsync)(int fd);
int (*vfs_unlink)(constchar *path);
int (*vfs_rename)(constchar *oldpath, constchar *newpath);
int (*vfs_fallocate)(int fd, off_t offset, off_t len);
int (*vfs_ftruncate)(int fd, off_t len);
 DIR *(*vfs_opendir)(constchar *path);
struct dirent *(*vfs_readdir)(DIR *dir);
int (*vfs_closedir)(DIR *dir);
int (*vfs_mkdir)(constchar *path, mode_t mode);
int (*vfs_rmdir)(constchar *path);
conststruct vfs_mgr* (*vfs_mgr_func)(const char *path);
} vfs_mgr;

PolarDB PostgreSQL内核创建了全局数组vfs_mgr polar_vfs[]和全局变量polar_vfs_switch,其中polar_vfs[0]默认挂载Linux内核提供的open、read、write等文件I/O操作函数,polar_vfs[1]中的文件I/O操作函数默认为NULL,可以挂载为PolarDB VFS层实现的vfs_open、vfs_read、vfs_write等文件I/O操作函数。基于此,PolarDB PostgreSQL内核提供了polar_open、polar_read、polar_write等文件I/O操作函数,polar_*相关函数利用polar_vfs和polar_vfs_switch实现了转发操作,均是直接调用的polar_vfs[polar_vfs_switch].*相关函数实现的。

由于PolarDB VFS层实现在插件polar_vfs中,因此如下图所示,共享存储模式下,当polar_vfs插件加载后,可以将polar_vfs_switch切换为1,这样PolarDB PostgreSQL内核其他模版调用polar_*相关函数时,便被转发到了PolarDB VFS模块实现的vfs_*文件I/O操作函数中。

同样的原理,PolarDB VFS层通过全局数组vfs_mgr vfs[]将不同文件系统实现的I/O操作函数进行汇聚,通过路径协议来将一个文件的I/O操作转发到对应的文件系统实现的接口中,具体如下图所示。

image.png

VFS模块使用

PolarDB VFS层模块主要涉及到以下几个组件:polar_vfs插件、polar_datadir路径配置参数、polar_enable_shared_storage_mode共享存储配置参数。

  • polar_vfs插件默认放到polar_internal_shared_preload_libraries参数中,被PolarDB PostgreSQL内核启动时默认加载;

  • polar_datadir路径配置了共享存储路径下位置,其中包含的路径协议表明了该路径下文件的I/O操作函数最终转发到的具体文件系统实现类别,关于共享存储路径下存储的内容,将会在接下来的文章中介绍;

  • polar_enable_shared_storage_mode配置了该节点是否开启共享存储模式,只有打开了该参数,才可以使能PolarDB VFS模块正常工作。

具体的部署方式,可以参见前述文章“PolarDB PostgreSQL版手动部署与共享存储配置介绍”。


文章转载自PolarDB,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论