C++项目实战:SPDK文件系统

目录

  • 一、Blobstore设计框架
  • 二、Cache机制
  • 三、Blob FS I/O操作
  • 四、SPDK FUSE (Filesystem in Userspcae)

前言

Blob FS是spdk面向于用户态的轻量级的文件系统

SPDK通过绕过内核(kernel bypass)的方案,构筑了用户态驱动,并利用异步轮询、无锁机制等,极大地提升了I/O性能。然而,正因为采用了kernel bypass的设计,使得原本内核中的文件系统不能使用。因此,SPDK提供了Blobstore用来支持上层存储服务,并基于此封装了Blob FS(Blob Filesystem)文件系统。

一、Blobstore设计框架

Blob FS被设计为面向Blobstore的轻量级文件系统,它提供给用户基本的文件操作: read、write、open、delete等。在介绍Blob FS的框架之前,首先介绍两个概念spdk_io_device和spdk_io_channel,在SPDK的早期设计中,spdk_io_device被设计为存储设备的抽象,并将特定线程的队列抽象为spdk_io_channel。这样的好处是为了避免竞争以及其带来的全局锁定,在SPDK线程模型中,每个spdk_thread通过各自的spdk_io_channel对spdk_io_device进行访问,这样不同的spdk_thread被隔离。这种类似的设计被推广,spdk_io_device被抽象成任何地址,不仅仅是底层存储设备的映射,也包含了对线程资源的逻辑管理结构。spdk_io_channel也随之被抽象成与spdk_io_device相关联的线程上下文,通过spdk_get_io_channel()函数,可以很方便的获取某个spdk_io_device上对应的channel。在SPDK中,所有的spdk_io_device会通过RB_TREE来维护,这有利于查找。

Blob FS在工作状态下会注册两个spdk_io_device,分别是blobfs_md以及blobfs_sync,前者带有md后缀,在Blob FS框架下,这被设计为与元数据(metadata)的操作有关,例如create,后者则是与I/O(read & write)操作有关。两个spdk_io_device绑定在一个reactor 0上,相当于对外提供了两个交互通道。根据前文所述,不同的spdk_thread没有办法共用一个spdk_channel,这就保证了只有reactor 0才能Blob FS进行交互,有效避免了多线程之间的竞争以及同步问题,例如对元数据的操作只能经由reactor 0实现,其他用户线程或者绑定在其他线程中的reactor对元数据的操作均需要通过SPDK中的消息机制来实现,交由reactor 0来进行处理,这种设计与SPDK的run-to-completion理念相符,所以工作流程可总结如下图所示。

二、Cache机制

为了加速文件的I/O性能,Blob FS提供了一套cache机制。DPDK提供的大页管理是SPDK实现零拷贝机制的基础,实际上这也是Blob FS中cache机制的基础。借助DPDK内存池对大页的管理,一次性申请到了一块较大的缓冲区mempool,该区域除了头部以外主要由固定大小的内存单元组成,并构成了ring队列,可方便的用于存取数据。

针对内存池对大页的管理,DPDK用到的接口主要有三个,SPDK对其进行了封装:

在Blob FS中,固定大小的内存单元其大小被设置为CACHE_BUFFER_SIZE,该值体现了cache机制中基本的存储单元,内存单元的数量可以采用默认值也可以通过Blob FS预留的接口进行重新设置。为了方便管理整个cache机制中的内存,Blob FS创建了一个新的spdk_thread线程g_cache_pool_thread。它主要维护了g_caches和g_cache_pool两个数据结构,前者维护了所有拥有cache的文件列表,后者则指向了前文提到的借助DPDK大页管理所申请到的内存池。与此同时,在该线程上还注册了一个poller函数用于监测内存池的使用情况,当内存池中空闲内存单元数量下降到20%以下时,会对已缓存的内存池对象进行清理释放,将内存单元返还给内存池,并且会优先释放低优先级的文件缓存,用户程序可根据需要调整缓存文件的优先级。

Blob FS对文件的管理依赖了spdk_file数据结构,在spdk_file中利用了cache_tree数据结构来对该文件的cache进行管理。cache tree由多层树状节点构成,维护了两种数据节点: tree node和buffer node,其中tree node充当了索引的作用,他可以根据根节点以及对应的offset,自上而下查找对应的buffer node;buffer node是实际缓存文件数据的节点,他位于整个cache tree的最底层,buffer node中用于缓存文件数据的空间实际上就是前文中提到的借助内存池申请到的一个个内存单元,因此单个buffer node中所能缓存文件数据的大小也就是CACHE_BUFFER_SIZE,在默认情况下,该值为256KB。

三、Blob FS I/O操作

尽管Blob FS中提供了同步和异步两种I/O操作,但当前集成并使用的是同步读。

1. spdk_file_read

首先,Blob FS会依据本次读取数据的大小进行判断,当读取数据大于CACHE_READAHEAD_THRESHOLD(默认情况下,该值为128KB)时,触发异步预读(readahead)操作,提前将一部分数据读取到内存中,随后对读取的数据进行切分,使得每次读取数据不超过buffer node的大小,即CACHE_BUFFER_SIZE的值。切分以后的读取,会先根据当前offset的值在cache tree中查询对应的buffer node,如果可以找到对应的buffer node节点,即说明缓存命中,直接将其缓存的文件数据执行memcpy拷贝到payload中,否则则需要通过Blobstore提供的异步读取直接从存储设备读取,并利用sem信号量进行同步,直到所有的读取完成,一次性返回整个payload,所以整个读取过程需要等待所有的payload准备完成才会返回。

2. spdk_file_write

目前SPDK主分支中的Blob FS提供的写入接口当前仅支持append类型,即不支持覆盖写入操作(注1)。对于append类型写入,Blob FS会首先检查其是否满足cache机制条件,如果不满足则借助Blobstore提供的写入接口,直接写入存储设备中。而一旦满足cache机制,则利用spdk_mempool_get函数向内存池中申请一个内存单元作为buffer node用于存储文件数据,随后将写入的payload进行切分,保证每次写入数据不超该buffer node的大小,并利用memcpy拷贝至buffer node中,当当前buffer node已被写满但存储文件还未被完全写入时,会将当前buffer node添加到cache tree中,再重新申请内存单元,重复上述操作,直到所有的payload都被写入buffer node中。随后触发异步flush操作,将cache tree中存储的文件数据利用Blobstore写入到存储设备中,并更新内存中的元数据。

从上述I/O过程可以发现,cache机制起到的加速作用主要体现在两点:

Read阶段中利用预读机制,先将当前offset附近的部分数据从存储设备中读入到内存中,方便下次直接从内存中读取,而不借助Blobstore,从而提升效率。

Write阶段中将payload优先写入到cache tree中,再利用异步flush操作写入到存储设备中,write本身不需要等待在落盘结束。

值得注意的是,分析Blob FS中cache的默认参数配置以及机制设计,可以发现Blob FS提供的cache机制更适用于大文件的读取。

注1:Blob FS对随机写的支持可参考 https://review.spdk.io/gerrit/c/spdk/spdk/+/5420,但是对目前的Blob FS cache机制有影响。更多Blob FS的patch,也可以关注https://review.spdk.io/。

四、SPDK FUSE (Filesystem in Userspcae)

SPDK提供了FUSE插件,可以将Blob FS像内核文件系统一样挂载,方便测试。可利用本地NVMe设备,基于SPDK FUSE挂载Blob FS,方法可参考以下步骤:

1.  ./configure --with-fuse && make  
2.  scripts/gen_nvme.sh --json-with-subsystems > config.json 
3.  ./test/blobfs/mkfs/mkfs config.json Nvme0n1 
4.  mkdir /mnt/fuse 
5.  ./test/blobfs/fuse/fuse config.json Nvme0n1 /mnt/fuse 

当然,也可以借助rpc框架,调用bdev子系统中Malloc Bdev模块,启用Blob FS文件系统,启用方法如下:

1.  ./build/bin/spdk_tgt  //  Terminal A
2.  ./scripts/rpc.py bdev_malloc_create 512 4096  // Terminal B
3.  ./scripts/rpc.py blobfs_create Malloc0 
4.  ./scripts/rpc.py blobfs_mount Malloc0 /mnt/fuse 

注意:Blobstore本身提供了持久化存储服务,但是这也要求面向的Bdev对象提供持久化存储,例如NVMe Bdev,而前文rpc调用的Malloc Bdev并不能提供持久化存储,因此基于Malloc Bdev模块的Blobstore不具有持久化存储能力。

总结

本文对SPDK提供的用户态存储服务Blobstore以及Blob FS进行了更为深入的探讨,对其设计细节进行了补充,并结合cache机制,分析了Blob FS所提供的I/O操作的流程,最后提供了借助FUSE插件对Blob FS进行调试分析的两种方法。

粉丝福利, 免费领取C/C++ 开发学习资料包、技术视频/项目代码,1000道大厂面试题,内容包括(C++基础,网络编程,数据库,中间件,后端开发/音视频开发/Qt开发/游戏开发/Linuxn内核等进阶学习资料和最佳学习路线)↓↓↓↓↓↓见下面↓↓文章底部点击免费领取↓↓

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java输入输出语句 和 保留字

目录 键盘输入语句 保留字 键盘输入语句 Input.java , 需要一个 扫描器(对象), 就是Scanner 步骤 : 导入该类的所在包, java.util.*创建该类对象(声明变量)调用里面的功能 案例要求:可以从控制台接收用户信息,【姓…

天然健康:源自大自然的馈赠

我们的农产品,承载着乡村的淳朴与大自然的馈赠。我们精选每一片土地,用科学种植方法,打造出品质卓越的农产品。无论是色泽鲜艳、口感脆嫩的蔬菜,还是香甜可口、营养丰富的水果,都让您在品尝美味的同时,享受…

记录一个利用winhex进行图片隐写分离的

前提 是一次大比武里面的题目,属实给我开了眼,跟我之前掌握的关于隐写合并的操作都不一样。 它不是直接在文件里面进行输入文件隐写,叫你输入密码,或者更改颜色,或者偏移位置; 它不是单纯几个文件合并&a…

css 三角形

方法一&#xff1a; <div class"triangle"></div>css .triangle{width: 8px;height: 8px;border: 8px solid #3C69EF;/* border-radius: 0px 2px 0 0; */ // 右上角加一点圆角border-block-end: 8px solid transparent;border-inline-start: 8px solid…

Pikachu靶场--文件包含

参考借鉴 Pikachu靶场之文件包含漏洞详解_pikachu文件包含-CSDN博客 文件包含&#xff08;CTF教程&#xff0c;Web安全渗透入门&#xff09;__bilibili File Inclusion(local) 查找废弃隐藏文件 随机选一个然后提交查询 URL中出现filenamefile2.php filename是file2.php&…

3d中模型显示黑色给不了材质---模大狮模型网

如果3D模型显示黑色&#xff0c;而且无法给它添加材质&#xff0c;可能有以下几种原因&#xff1a; 一&#xff1a;模型没有UV贴图 UV贴图是3D模型表面纹理的一种方式&#xff0c;如果模型没有正确的UV贴图&#xff0c;渲染时可能会显示黑色。在大多数3D建模软件中&#xff0c…

【植物大战僵尸】C语言简易版

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f4a5;&#x1f4a5;个人主页&#xff1a;奋斗的小羊 &#x1f4a5;&#x1f4a5;所属专栏&#xff1a;C语言 &#x1f680;本系列文章为个人学习…

如何用Vue3打造一个炫酷的树状图

本文由ScriptEcho平台提供技术支持 项目地址&#xff1a;传送门 基于 Vue.js 的 Treemap 可视化组件 应用场景介绍 Treemap 可视化组件是一种强大的工具&#xff0c;用于以直观的方式展示分层数据。它将数据点绘制为矩形&#xff0c;其中每个矩形的大小与数据点的大小成正比…

SSM考研咨询app-计算机毕业设计源码05262

摘 要 随着互联网趋势的到来&#xff0c;各行各业都在考虑利用互联网将自己推广出去&#xff0c;最好方式就是建立自己的互联网系统&#xff0c;并对其进行维护和管理。在现实运用中&#xff0c;应用软件的工作规则和开发步骤&#xff0c;采用Java技术建设考研咨询app。 本设计…

Notes客户机开启事务日志

大家好&#xff0c;才是真的好。 了解过事务日志的人都知道——等等&#xff0c;你还不知道事务日志&#xff1f; 那我们先介绍一下&#xff0c;简单来说&#xff0c;Domino事务日志是捕获数据库更改并将其写入的记录&#xff0c;然后等服务器不繁忙或按计划更新到磁盘上的No…

ASP.NET MVC-简单例子

环境&#xff1a; win10&#xff0c;.NET Framework 4.6.1 参考&#xff1a; ASP.NET MVC 简介 | 菜鸟教程 https://www.runoob.com/aspnet/mvc-intro.html 准备 查看 net framework 版本: cmd-> C:\Windows\Microsoft.NET\Framework\v4.0.30319>MSBuild /version Mic…

使用 Hugging Face 推理终端搭建强大的“语音识别 + 说话人分割 + 投机解码”工作流

Whisper 是当前最先进的开源语音识别模型之一&#xff0c;毫无疑问&#xff0c;也是应用最广泛的模型。如果你想部署 Whisper 模型&#xff0c;Hugging Face推理终端能够让你开箱即用地轻松部署任何 Whisper 模型。但是&#xff0c;如果你还想叠加其它功能&#xff0c;如用于分…

电路分析期末总结笔记上

电流&#xff0c;电压定义及单位 电流&#xff08;Current&#xff09; 的定义是单位时间内通过导体横截面的电荷量。 电压&#xff08;Voltage&#xff09;&#xff0c;又称作电势差或电位差&#xff0c;是衡量单位电荷在静电场中由于电势不同而产生的能量差的物理量。 参考…

Python期末复习题库(上)

1. (单选题) Python源程序的扩展名为&#xff08; A &#xff09; A. py B. c C. class D. ph 2. (单选题) 下列&#xff08; A &#xff09;符合可用于注释Python代码。 A. # B. */ C. // D. $ 3. (单选题)下列关于Python 语言的特点的说法中&#xff0c;错误的是&#xf…

Apache Flink详解:流处理与批处理的强大框架

Apache Flink详解&#xff1a;流处理与批处理的强大框架 Apache Flink是一个开源的流处理框架&#xff0c;旨在处理大规模数据流。Flink能够处理实时流数据和批处理数据&#xff0c;具有高吞吐量、低延迟、容错等特性。以下是对Flink的详细介绍&#xff1a; 核心概念 流与批处…

C++学习/复习15--栈与队列概述及练习/deque/适配器的概念

1.1stack概念 1.2stack函数 1.3最小栈 1.4栈的压入弹出 1.5逆波兰表达式 1.6栈实现队列 1.7层序遍历 1.8stack模拟实现 2.1queue概念 2.2queue函数 2.3queue模拟实现 3.1deque适配器 3.2deque功能 3.3deque原理 3.4deque特点与适配器

MS1004激光测距用高精度时间测量(TDC)电路

品简述 MS1004 是一款高精度时间测量 (TDC) 电路&#xff0c;对比 MS1002 具 有更高的精度和更小的封装&#xff0c;适合于高精度小封装的应用领域。 MS1004 具有双通道、多脉冲的采样能力、高速 SPI 通讯、 多种测量模式&#xff0c;适合于激光雷达和激光测距。 主…

每天一个数据分析题(三百五十八)-图表决策树

图中是某公司记录销售情况相关的表建立好的多维分析模型&#xff0c;请根据模型回答以下问题&#xff1a; 1&#xff09;该模型属于哪种连接模式&#xff1f; A. 星型模式雪花模式 B. 星座模式雪花模式 C. 星座模式星型模式雪花模式 D. 以上都不对 数据分析认证考试介绍…

微信小程序添加服务类目|《非经营性互联网信息服务备案核准》怎么获取

根据客服反馈&#xff0c;《非经营性互联网信息服务备案核准》在工业和信息化部政务服务平台网站查询&#xff0c;查询结果的截图就是《非经营性互联网信息服务备案核准》。 工业和信息化部政务服务平台 《非经营性互联网信息服务备案核准》&#xff1a; 与客服聊天的截图&a…

Kubesphere替换出错的pod

我们的开发是远程docker进行打包&#xff0c;昨天早上一来发现打包的时候提示docker.io连接超时报错&#xff0c;于是便觉得应该是dockerhub被墙的问题&#xff0c;就在远程docker里面增加了registryMirrors的配置&#xff1b;改完之后顺手就重启了docker&#xff0c;于是打包没…