SPDK介绍

SPDK简介

概念(什么是SPDK)

英特尔开发了SPDK(Storage Performance Development Kit),包含一套驱动程序,以及一整套端到端的存储参考架构。
首先要明确spdk是一个框架,而不是一个分布式系统,spdk的基石是
用户态(user space)、轮询(polled-mode)、异步(asynchronous)、无锁(lockless)
SPDK基于Nvme驱动提供了零拷贝、高并发直接从用户态访问ssd的特性。
其最初的目的是为了优化块存储落盘。但随着spdk的持续演进,大家发现spdk可以优化存储软件栈的各个方面。很多分布式存储系统都在思考如何吸纳spdk框架,或是采用spdk代表的高性能存储技术,来优化整条IO链路。

使用SPDK原因

固态硬盘SSD正在迅速扩展它在数据中心中的份额,相较于传统存储介质,相较于传统机械硬盘性能耗电等优势明显。随着更新的闪存介质投入市场(如3D NAND),这些优势还在不断扩大。

这些新的设备目前大都基于NVMe:NVMe准确的说是目前最新的存储设备通信协议。现在一块基于NVMe的SSD硬盘的性能比一个企业级磁盘阵列还要好。

用户在集成新一代的NVMe设备,会碰到很大的挑战。因为NVMe硬盘的吞吐量和时延表现太好了就IOPS而言,比传统SAS或SATA温氏磁盘快上千倍,也比之前的SATA SSD快5~10倍。一般存储软件的表现,相对于NVMe来说,在整个IO事务中消耗的时间百分比就显得太多了。

nvme(硬件)已经快到一定程度了,尤其是软件已经赶不上他了,此时软件反而成为了系统IO的瓶颈。换句话说,存储软件栈的性能和效率在整个存储系统中越来越重要。

举个例子:我们从北京乘飞机到美国加州,按照当前的飞行速度(假设为机械硬盘),在天上需要13个小时。这种情况下,你安检的时间,过海关的时间,候机的时间,加起来3个小时,相对于总共的13+3=16个小时也不算长。设想现在飞机的飞行速度(硬件速度)提高了100倍(使用了NVME设备),不到10分钟的飞行时间,就可在加州落地,这时3个小时(软件速度)的地面手续就显得太长了。这时软件拖慢了整体时间,我们就需要提高安检,候机时间等,也就是提高软件效率

SPDK就是做这件事的。

SPDK关键技术

相对于传统IO方式,SPDK运用了以下关键技术实现其高性能方案。

1.用户态(空间)

定义:什么是用户空间:Kernel space 是 Linux 内核的运行空间,User space 是用户程序的运行空间。为了安全系统稳定性,它们是隔离的,即使用户的程序崩溃了,内核也不受影响
Kernel space 可以执行任意命令,调用系统的一切资源;User space 只能执行简单的运算,不能直接调用系统资源,必须通过系统接口(又称 system call),才能向内核发出指令也叫系统调用。

SPDK运行在用户态的实现

第一:驱动是一个直接连接并控制计算机硬件的软件。
第二:操作系统将根据权限级别将系统虚拟内存分为两类:用户空间和内核空间。
通常情况,驱动运行在内核空间,我们应用程序访问磁盘,读取网卡的数据,新建一个线程都需要通过系统调用接口,完成从用户态到内存态的切换
但是SPDK包含的驱动运行在用户空间,但是这些驱动仍旧直接和硬件设备相连。也就是直接绕过内核空间。

SPDK为了控制硬件设备,他先指示操作系统放弃对该硬件的控制,这样就不会走内核空间了。比如在Linux上解除NvMe设备的绑定,则对应的/dev/nvme1就会消失。然后通过驱动直接控制硬件设备这样更快。

SPDK选择用户态的好处

传统IO是在用户态和内核态频繁切换,这会造成大量开销。而我们的设备驱动代码运行在用户态意味着,在定义上驱动代码不会运行在内核中。减少系统调用,避免内核上下文切换和中断的处理开销,从而节省了大量的CPU负担。允许更多的时间被用来做实际的数据存储。

2. 轮询模式

采用轮询模式改变了传统I/O的基本模型。

传统方式IO方式

一般来说读写数据的运作方式是这样的:
OS kernel请求一组数据,硬盘回应“嗯,没问题”,但是磁盘IO较慢,所以需要一点时间来准备数据,准备好了就会告诉OS kernel准备好了。假设现在已经准备好了,就会给CPU发送一个中断信号,通知OS说我的数据准备好了,可以来取数据了。这就是中断的方式

有IO需要处理时就请求一个中断,CPU先去处理其他事务,等收到中断后才进行资源调度来处理IO。

但是注意中断是有开销的,需要切换资源。

轮询工作

当磁盘速度远慢于CPU时,CPU中断处理资源充沛,中断机制是能对这些IO任务应对自如的。

但是当硬盘设备速度很快,马上就可以把数据准备好,也就是磁盘IO几乎不需要等待了,再使用中断,本来硬盘IO数据立刻都准备好了,而CPU切换到其他地方执行去了,然后再中断回来取数据,这就会造成没必要的开销并且对性能造成影响。

在低速设备中,中断开销只占整个I/O时间的一个很小的百分比。然而,在固态设备的时代,持续引入更低延迟的持久化设备,中断开销成为了整个I/O时间中不能被忽视的部分。继续使用中断的方式会大大浪费硬盘性能。

所以解决方案:对于超高速设备(比如这里的nvme磁盘,基于RAM的缓存盘)以一种叫做“轮询”的模式运作。

所以我们采用轮询的工作方式:我们提交完io 请求之后,就一直通过轮询的方式来判断io 请求是否完成。SPDK架构中也是通过这样的方式,而不是依靠中断,在高速设备上用于取代中断的访问方式。这样会一直占用CPU,但是由于硬盘IO很快,这样带来的好处是降低总延迟和延迟抖动。通俗的来讲spdk运行时会占用满指定的CPU core,其本质就是一个大的while死循环,占满一个cpu core。去连续的跑用户指定的poller,轮询队列。

注意:是中断驱动处理还是轮询驱动处理,取决于系统硬件的搭配方式,不同的条件会匹配不同的优化策略。我们使用轮询是因为使用高速存储设备存储IO速度极快。

3. 线程无锁

spdk设计的主要目标之一就随着使用硬件(e.g. SSD,NIC,CPU)的增多而获得性能的线性提升,为了达到这目的,spdk的设计者就必须消除使用更多的系统资源带来的过载,如:更多的线程、进程间通信,访问更多的存储硬件、网卡带来的性能损耗。

spdk引入了无锁队列,使用lock-free编程,从而避免锁带来的性能损耗。

spdk的无锁队列主要依赖的dpdk的实现,其本质是使用CAS(compare and swap)实现了多生产者多消费者FIFO队列。

SPDK运行在用户空间:比如和应用绑定,因为线程是应用本身自己创建的这些线程,这样创建的线程就可以很方便被维护(比如数量)。SPDK驱动会将硬件队列直接暴露给应用(因为驱动在用户空间),应用被要求每次只能从一个线程访问一个硬件队列。这保证了:每个线程提交请求的时候不需要和其他线程协调(比如通过锁协调)因为每个线程控制一个硬件队列,这样避免了冲突。实现无锁。

4. 异步

SDPK提供的了大量的异步接口
spdk_bs_init(bs_dev, NULL, bs_init_complete, hello_context);
使用异步好处:是不会阻塞当前程序的执行,并且在操作完成之后调用回调函数。
通过轮询实现

SPDK架构介绍

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

SPDK各层解析

1. client software就是

client software就是产生数据的部分,比如mysql数据库中的要存储到硬件设备上的数据。

2. 数据存储协议层

比如使用的是SCSI协议或者NVME协议,将上面的数据通过不同的传输通信协议发送给下层。
每个种类的接口可以使用不同的通信协议,不同通信协议是决定传输速度的关键因素。比如我们的网络层,同一个网络可以有不同的传输协议比如TCP或者UDP。

3. 存储服务层 BDAL(BDEV)

数据块抽象层。
spdk提供了块设备(bdev)的软件栈,这个块设备并不是linux系统中的块设备,spdk中的块设备只是软件抽象出的接口层。

spdk已经提供了各种bdev,满足不同的后端存储方式、测试需求。如NVMe (NVMe bdev既有NVMe物理盘,也包括NVMeof)、内存(malloc bdev)、不落盘直接返回(null bdev)等等。用户也可以自定义自己的bdev,一个很常见的使用spdk的方式是,用户定义自己的bdev,用以访问自己的分布式存储集群。

blobstore层

块设备抽象,旨在等同于操作系统块存储层,该层通常位于传统内核存储堆栈中设备驱动程序的正上方。
blobstore是BDAL层的具体技术实现,使用blobstore技术,将后端存储层都抽象成一个存储块。提供给上层进行存储。上层将BDAL当成一个整体的存储介质就并提供存储接口给上层。

他可以将后端存储设备(如NVMe (NVMe bdev既有NVMe物理盘,也包括NVMeof)、内存(malloc bdev)分割成不同的存储单元blob,然后向blob中存储数据。

4. 后端块设备

通过BDAL,我们可以将数据存储到不同的地方比如AIO文件系统,再比如malloc内存,再比如NVME 协议。通过这些,就可以将数据落到物理存储介质。比如通过NVME直接将数据存放到NVME SSD固态硬盘。

总结

spdk目前的的应用场景主要是针对块存储,可以说块存储的整个存储的基石,再其之上我们又构建了各种文件存储、对象存储、表格存储、数据库等等。

参考资料

https://zhuanlan.zhihu.com/p/362978954
https://blog.csdn.net/weixin_40343504/article/details/88706733
https://www.optbbs.com/forum.php?mod=viewthread&tid=14642318
https://blog.csdn.net/zlarm/article/details/79140299

SPDK(存储性能开发套件)官方文档中文版。 第一章 简介 1 1.1.什么是SPDK? 1 1.2.入门 1 1.3. Vagrant开发环境 3 1.4.更新日志(略) 6 第二章 概念 6 2.1. 用户空间驱动程序** 6 2.2. 来自用户空间的DMA** 7 2.3. 消息传递和并发** 9 2.4. NAND Flash SSD内部 13 2.5. 将I / O提交到NVMe设备** 15 2.5.1 NVMe规范 15 2.5.2 SPDK NVMe驱动程序I / O路径 15 2.6. 使用Vhost-user进行虚拟化I / O. 16 2.6.1 介绍 16 2.6.2 QEMU 17 2.6.3 设备初始化 18 2.6.4 I / O路径 19 2.6.5 SPDK优化 20 2.7. SPDK目录结构概述 20 2.8. SPDK移植指南 22 第三章 用户指南 22 3.1. 系统配置用户指南 22 3.1.1 IOMMU配置 22 3.2. SPDK应用程序概述 23 3.2.1 配置SPDK应用程序 23 3.3. iSCSI Target 26 3.3.1. iSCSI Target入门指南 26 3.3.2. 通过配置文件配置iSCSI Target 27 3.3.3. 通过RPC方法配置iSCSI Target 28 3.3.4. 配置iSCSI启动器 29 3.3.5. rpc配置示例*** 30 3.3.6. iSCSI 热插拔 32 3.4. NVMe over Fabrics Target 32 3.5. Vhost Target(略) 37 3.6 块设备用户指南 38 3.6.1 bdev介绍 38 3.6.2 通用RPC命令 38 3.6.3 Ceph RBD 39 3.6.4 压缩虚拟Bdev模块 40 3.6.5 加密虚拟Bdev模块 41 3.6.6 延迟vbdev模块 41 3.6.7 GPT(GUID分区表) 42 3.6.8 iSCSI bdev 43 3.6.9 Linux AIO bdev 43 3.6.10 OCF虚拟bdev 43 3.6.11 Malloc bdev 44 3.6.12 NULL bdev 44 3.6.13 NVMe bdev 44 3.6.14 逻辑卷Lvol 45 3.6.15 RAID 46 3.6.16 Passthru 46 3.6.17 Pmem 46 3.6.18 Virtio Block 47 3.6.19 Virtio SCSI 47 3.7 BlobFS(Blobstore文件系统) 48 3.7.1 RocksDB集成 48 3.7.2 FUSE插件 49 3.8 JSON-RPC方法(略) 49 第四章 程序员指南 49 4.1. Blobstore程序员指南 49 4.1.1 介绍 50 4.1.2 运作理论 50 4.1.3 设计注意事项 52 4.1.4 例子 54 4.1.5配置 54 4.1.6 组件细节 54 4.2. 块设备层编程指南 56 4.3 编写自定义块设备模块 58 4.3.1 介绍 58 4.3.2 创建一个新模块 59 4.3.3创建虚拟Bdev 60 4.4 NVMe over Fabrics目标编程指南 61 4.4.1 介绍 61 4.4.2 原语结构体 61 4.4.3 基础函数 62 4.4.4访问控制 62 4.4.5发现子系统 62 4.4.6 传输 63 4.4.7选择线程模型 63 4.4.8 跨CPU核心扩展 63 4.4.9 零拷贝支持 63 4.4.10 RDMA 63 4.5 Flash传输层 64 4.5.1 术语 64 4.5.2 使用方法 67 4.6 GDB宏用户指南 69 4.6.1 介绍 69 4.6.2 加载gdb宏 71 4.6.3 使用gdb数据目录 72 4.6.4 使用.gdbinit加载宏 72 4.6.5 为什么我们需要显式调用spdk_load_macros 72 4.6.6 以上可用的宏总结 73 4.6.7 添加新宏 73 4.7 SPDK “Reduce”块压缩算法 73 4.7.1 介绍 73 4.7.2 例子 74 4.8 通知库 78 第五章 基本信息 79 5.1 事件框架 79 5.1.1 事件框架设计注意事项 80 5.1.2 SPDK事件框架组件 80 5.1.3 应用框架 80 5.2 逻辑卷 81 5.2.1 术语 81 5.2.2 配置逻辑卷 84 5.3 矢量数据包处理(略) 86 第六章 杂项 86 6.1 介绍 86 6.2 NVMe的P2P API 86 6.3 确定设备支持 87 6.4 P2P问题 87 第七章 驱动程序 88 7.1 NVMe驱动程序*** 88 7.1.1 介绍 88 7.1.2 例子 88 7.1.3 公共接口 89 7.1.4 NVMe驱动程序设计 89 7.1.5 NVMe over Fabrics主机支持 91 7.1.6 NVMe多进程 91 7.1.7 NVMe Hotplug 92 7.2 I/OAT驱动程序 93 7.2.1 公共接口 93 7.2.2 关键功能 93 7.3 Virtio驱动程序 93 7.3.1 介绍 93 7.3.2 2MB大页面 93 第八章 工具 94 8.1 SPDK CLI 94 8.1.1 安装所需的依赖项 94 8.1.2 运行SPDK应用程序实例 94 8.1.3 运行SPDK CLI 94 8.1.4 可选 - 创建Python虚拟环境 94 8.2 nvme-CLI 95 8.2.1 nvme-cli with SPDK入门指南 95 8.2.2 使用场景 95 第九章 性能测试报告(略) 96 第十章NVMe-oF Target跟踪点*** 96 10.1 介绍 96 10.2 启用跟踪点 97 10.3 捕获事件的快照 97 10.4 捕获足够的跟踪事件 98 10.5 添加新的跟踪点 99
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Charles Ray

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

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

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

打赏作者

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

抵扣说明:

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

余额充值