spdk技术原理简介和实践经验

news2024/12/24 3:06:45

一、导读

与机械硬盘相比,NVMe-ssd在性能、功耗和密度上都有巨大的优势,并且随着固态存储介质的高速发展,其价格也在大幅下降,这些优势使得NVMe-ssd在分布式存储中使用越来越广泛。由于NVMe-ssd的性能比传统磁盘介质高出很多,使得在整个IO处理过程中,软件部分占用的时间比例大大提升,成为制约存储系统性能的主要因素。为了充分发挥后端NVMe-ssd的性能,intel开发出了存储性能开发工具包-SPDK(Storage Performance Development Kit),和RDMA一样,SPDK也采用了kernel bypass的思想,它提供了一整套工具和库,以实现高性能、全用户态、扩展性强的存储应用程序,旨在大幅缩减存储I/O栈的软件开销,将固态存储介质的性能发挥到极致。

本文先对SPDK 技术进行介绍,更好的了解其实现原理,深入理解其带来性能大幅提升的原因,然后给大家分享下中国移动云能力中心块存储团队将SPDK应用到分布式块存储软件BC-EBS上做的一些工作和使用经验。

二、SPDK技术原理简介

1、SPDK的整体架构

SPDK架构整体分为三层:

存储协议层:SPDK支持的存储应用类型。NVMe-oF target实现了NVMe-oF规范,对外提供基于NVMe协议的存储服务端,支持RDMA和TCP网络;iSCSI Target对外提供基于SCSI协议的存储服务端;vhost-scsi或vhost-blk对qemu提供后端存储服务,qemu可以基于SPDK提供的后端存储为虚拟机挂载virtio-scsi或virtio-blk磁盘。

存储服务层:SPDK bdev相当于内核通用块层,为不同后端设备(NVMe、AIO、RBD、VIRTIO 、ISCSI等)驱动提供通用的API接口。SPDK还在通用块层实现了QoS、磁盘阵列、逻辑卷管理等功能。

驱动层:为不同的后端存储设备提供驱动。图中把驱动细分成两层,和块设备强相关的放到了存储服务层,而把和硬件强相关部分放到了驱动层。

2、SPDK的工作机制

为了更好理解SPDK能实现高性能的原因,我们以下图中的场景为例,分析SPDK工作过程,详解工作过程中用到的关键技术。

图2 / SPDK的工作机制

在图中,一台服务器上插了一张NVMe-ssd卡,划分两个namespace(对操作系统而言,每个namespace相当于一块独立的盘),分别分配给两个虚机使用,采用的vhost-blk方式。根据vhost-user协议,qemu不再进行I/O的转发,只进行控制面的管理工作,如feature的协商、virtqueue初始化等,虚机的前端驱动和宿主机存储后端vhost通过共享内存来进行数据交互,具体的交互过程是基于virtio vring 环来实现的。

假如vm1要下发数据时,虚机将数据的内存地址(guest physical address,简称PGA)放在vring环上,vhost的reactor线程通过poller机制不断的轮询vring环,发现有新添数据时,根据qemu记录的PGA到宿主机虚拟地址(vhosthost virtual address,简称VVA)内存映射关系,使用rte_vhost_va_from_guest_pa函数将GPA转换为VVA供vhost处理。

vhost拿到数据后,经过SPDK bdev层的处理(如io拆分合并、对齐等),根据注册的设备驱动,找到具体的NVMe-ssd设备。为了防止多个thead操作同一个设备引起的资源竞争,SPDK提供了I/O channel的概念,每一个thead拥有不同的I/O channel,在NVMe 中,一个I/O channel就对应NVMe的一个队列(queue pair),这样数据最终就交由NVMe的队列来处理。在创建vhost-blk设备时,会选择reactor的一个线程进行绑定,这样,整个I/O处理过程都在同一个线程中完成。

SPDK能实现高性能,主要得益于以下几种技术:

(1)全用户态:把驱动移到用户态,避免了系统调用的开销,且真正实现了内存零拷贝。

在传统的存储I/O栈中,应用程序和磁盘驱动分别处于用户态和内核态,应用程序为了和磁盘进行交互,需要进行多次的系统调用,并且数据需要在用户空间和内核空间之间拷贝,这两个动作都增加了系统开销,当后端是高速设备时,这部分开销就表现的很突出。

而在SPDK中,将驱动程序移到用户态,在执行调用时避免了用户态和内核态来回切换,将节省大量的处理器时间开销,从而有更多的时钟周期来进行真正的存储工作。虚拟机的前端驱动和宿主机存储后端vhost通过共享内存传递数据,避免了大量的内存拷贝。I/O在宿主机上绕过了内核,路径更短。

(2)SPDK独立的线程模型:一个core只拥有一个thread,该thread上可以执行很多poller(轮询函数),满足run-to-completion(一个线程最好执行完所有的任务)的需求。

vhost进程启动时,可以配置多个轮询线程(SPDK称reactor),每个线程绑定一个core。在创建一个vhost-blk设备时,也需要为该设备绑定一个core,绑定的core和前面reactor的core一致。在每个线程上,SPDK提供了poller的机制,来处理具体的事务。SPDK提供的poller分两种:基于定时器的poller和非定时器的poller。在reactor的while(1)循环中,它会不停的check这些poller的状态,进行相应的调用,同时I/O也会得到相应的处理。由于单个core上只有一个reactor thread,所以同一个reactor thread 中不需要一些锁的机制来保护资源。

(3)线程间的通信方式:Event事件机制,一种轻量型的线程交互方式。

在传统存储模型中,多个线程操作同一个资源,往往是通过锁机制来实现的。为了使同一个thread只执行自己所管理的资源,SPDK提供了Event (事件调用) 机制。该机制的本质是每个reactor对应的数据结构 (struct SPDK_reactor) 维护了一个Event事件的ring (环)。这个环是多生产者和单消费者模型,即每个Reactor thread可以接收来自任何其他Reactor thread 的事件消息进行处理。当然,Event ring处理的同时也在执行reactor的SPDK_poller轮询函数。

每个Event事件的数据结构 (struct SPDK_event) 包括了需要执行的函数、相应的参数以及要执行的core。例如,Reactor A 向Reactor B通信,其实就是需要Reactor B代替Reator A执行函数F(X),这样他们只执行自己管理的资源,更加的高效 。

(4)数据路径的无锁化机制:在I/O路径上采用io_channel技术,避免采用锁机制,能降低时延和提升性能。

对于类似NVMe的多队列设备,SPDK提供一个I/O channel的概念 (即thread和device的一个mapping关系),封装在SPDK_vhost_blk_session结构中。不同的thread 操作同一个device应该拥有不同的I/O channel,每个I/O channel在I/O路径上使用自己独立的资源就可以避免资源竞争,从而去除锁的机制。如上图,后端是NVMe-ssd设备时,一个I/O channel对应NVMe的一个queue pair。

三、目前块存储团队在SPDK上的一些工作

1、ceph场景下使用SPDK遇到的性能问题

在虚拟化qemu+SPDK+librbd使用场景下,SPDK采用 vhost-blk或vhost-scsi协议,在虚机中,我们发现性能很差,不能充分发挥出后端ceph集群性能。通过排查发现,该问题的原因是当前SPDK的架构是为了发挥NVMe类设备的性能而设计的,其特点是SPDK下发的I/O会直接到达硬件,I/O的收割也是SPDK直接轮询硬件,而ceph场景下需要有额外的ceph线程介入来下发收割I/O。当前SPDK线程与ceph线程跑在同一个CPU上,造成了资源竞争,导致IO性能下降。解决方法是将这些ceph线程移到在非SPDK使用的CPU上。经过优化后,性能大幅提升,最大提升了16倍,均接近后端集群的性能。

图3 / 优化前后vhost-blk设备性能对比

图4 / 优化前后vhost-blk设备时延对比

图5 / 优化前后vhost-scsi设备性能对比

图6 / 优化前后vhost-blk设备性能对比

2、SPDK和ceph线程最优绑核方案探索

SPDK能有优异的性能,离不开它优异的线程模型,实际使用过程中核的分配相当重要,从上面可以看出,在后端是ceph的场景下,ceph线程运行的核如果没有规划,性能也可能会很差。在虚机场景下,qemu节点核资源更是有限,使得我们不得不考虑,在qemu+SPDK_vhost_iscsi+librbd方案下, 怎样将qemu节点有限的核资源分配给SPDK reactor和ceph线程, 才能达到最优的性能。下面我们就单SPDK线程、ceph卷占用的CPU核数不同时,对性能的影响,及在后端是ceph场景下,单reactor可发挥的最大性能进行了测试和分析。

(1)测试环境:

测试环境共4台服务器,SPDK和qemu共用一台机器,SPDK采用的vhost-scsi方式。

(2)单SPDK线程,ceph卷占用的CPU核数不同时,对性能的影响:

a、1个ceph卷的场景下,ceph卷绑不同数目的核时能发挥出的性能。其中横坐标表示ceph卷的绑核情况,纵坐标表示ceph卷能发挥的iops性能,单位为K。

图7 / 1个image下ceph线程绑核对性能的影响

b、2个ceph卷的场景下,ceph卷绑不同数目的核时能发挥出的性能。其中横坐标表示2个ceph卷的绑核情况,纵坐标表示2个ceph卷能发挥的总共iops性能,单位为K。

图8 / 2个image下ceph线程绑核对性能的影响

c、3个ceph卷的场景下,ceph卷绑不同数目的核时能发挥出的性能。其中横坐标表示3个ceph卷的绑核情况,纵坐标表示3个ceph卷能发挥的总共iops性能,单位为K。

图9 / 3个image下ceph线程绑核对性能的影响

(3)在后端是ceph场景下,单个reactor可发挥的最大性能(ceph集群随机写性能在140K iops左右):

a、每个卷绑定两个core,增加ceph卷的个数,单reactor下可发挥的最大性能。

图10 / 增加卷数,单reactor可发挥的最大性能

b、在上一步的基础上,5个卷时,增加每个卷绑核的数量,对性能的影响。

图11 / 单个reactor,5个卷,增加绑核可发挥的性能

c、增加reactor个数,和单reactor下的性能进行比较。

图12 / 2个reactor,5个卷,增加绑核可发挥的性能

(4)测试结果分析

a、从图7、8、9 可以看出,单reactor下,增加卷的绑核数,性能发挥出的越好。

b、从图10可以看出,单reactor下,每个卷绑两个核,增加卷的个数,性能发挥的越好,但随着卷的个数增加,性能趋于稳定。

c、由a得出的结论,增加卷的绑核数可以增加性能,在未达到集群最大性能的情况下,尝试5个卷时,增加绑核数,但性能并未增加,说明此场景下,单reactor的性能可能到了瓶颈。

d、为了进一步验证c中单个reactor是否到了性能瓶颈,增加reactor个数后,5个卷,相同的绑核数,可以看出性能发挥的更好,更接近集群最大性能。说明在后端为ceph集群,vhost_scsi+librbd的使用场景下,单reactor可发挥的最大性能在100K左右。

四、结尾

SPDK凭借其优秀的架构和性能获得各个存储厂家的青睐,但目前社区还不太成熟,在和各自的产品融合时,用户态的工作模式与传统内核态I/O模型有较大差异,可参考的使用经验不多,往往会遇到各种各样的问题。中国移动块存储团队目前也在积极的将SPDK引入到我们的块存储产品中,进行性能的优化提升,后续会将更多的使用和优化经验分享给大家,与大家一起进步。

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

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

相关文章

在 WLC上配置WPA2-Enterprise WLAN

实验大纲 第1部分:创建一个新的WLAN 第1步:创建一个新的VLAN接口 第2步:配置WLC让它使用RADIUS服务器 第3步:创建一个新的WLAN 第4步:配置WLAN安全策略 第2部分:配置DHCP范围和SNMP 第1步&#xff1…

【LeetCode: 2670. 找出不同元素数目差数组 + 哈希表 + 前后缀处理】

🚀 算法题 🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜,…

UFC762AE101 3BHE006412R0101

UFC762AE101 3BHE006412R0101 UFC762AE101 3BHE006412R0101 LG Innotek 开发出“车辆用 5G 通信模块” ... 。 LG Innotek 的“车辆用 5G 通信模块”的响应时间为 1ms(毫秒) ... 、存储器、RF 电路、C-V2X模块等 480 多个零部件。 LG Innotek ...…

TensorFlow2实战-系列教程4:数据增强

🧡💛💚TensorFlow2实战-系列教程 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Jupyter Notebook中进行 本篇文章配套的代码资源已经上传 猫狗识别1 数据增强 猫狗识别2------数据增强 猫狗识别3------迁移学习 对于图像数据…

前端入门第二天

目录 一、列表、表格、表单 二、列表(布局内容排列整齐的区域) 1.无序列表(不规定顺序) 2.有序列表(规定顺序) 3.定义列表(一个标题多个分类) 三、表格 1.表格结构标签 2.合并…

【Node-RED】node-red-contrib-opcua-server模块使用(4)

【Node-RED】node-red-contrib-opcua-server模块使用(4) 前言实现模块使用plc模拟地址空间编写缺点 前言 基于前几则博文的研究,经过偶像的点播,茅塞顿开。本期博文主要介绍如何实现openServer 信息的中转,获取各个pl…

2024年【中级消防设施操作员(考前冲刺)】找解析及中级消防设施操作员(考前冲刺)考试总结

题库来源:安全生产模拟考试一点通公众号小程序 2024年中级消防设施操作员(考前冲刺)找解析为正在备考中级消防设施操作员(考前冲刺)操作证的学员准备的理论考试专题,每个月更新的中级消防设施操作员&#…

国外知名的农业机器人公司

从高科技温室到云播种,农业机器人如何帮助农民填补劳动力短缺以及超市货架的短缺。 概要 “高科技农业”并不矛盾。当代农业经营更像是硅谷,而不是美国哥特式,拥有控制灌溉的应用程序、驾驶拖拉机的 GPS 系统和监控牲畜的带有 RFID 芯片的耳…

【Linux】进程通信——共享内存+消息队列+信号量

欢迎来到Cefler的博客😁 🕌博客主页:折纸花满衣 🏠个人专栏:题目解析 🌎推荐文章:【LeetCode】winter vacation training 目录 👉🏻共享内存👉🏻关…

亚马逊要怎么运营?亚马逊运营主要运营内容有哪些?

一个店铺的成长发展少不了运营,而店铺的运营必须要有相关运营经验,才能将店铺做好,近几年亚马逊电商平台在不断的发展,亚马逊的运营模式非常独特,它借助于多种技术解决方案来提供最佳的客户体验。那么亚马逊要怎么运营…

Java基础学习:System类和Static方法的实际使用

一、System类 1.在程序开发中,我们需要对这个运行的结果进行检验跟我们预判的结果是否一致,就会用到打印结果在控制台中显示出来使用到了System类。System类定义了一些和系统相关的属性和方法,它的属性和方法都是属于静态的,想使用…

备战蓝桥杯---数据结构与STL应用(入门4)

本专题主要是关于利用优先队列解决贪心选择上的“反悔”问题 话不多说,直接看题: 下面为分析: 很显然,我们在整体上以s[i]为基准,先把士兵按s[i]排好。然后,我们先求s[i]大的开始,即规定选人数…

事件驱动架构:使用Flask实现MinIO事件通知Webhooks

MinIO的事件通知可能一开始看起来并不激动人心,但一旦掌握了它们的力量,它们就能照亮您存储桶内的动态。事件通知是一个全面、高效的对象存储系统中的关键组件。Webhooks是我个人最喜欢的工具,用于与MinIO集成。它们在事件的世界中就像一把瑞…

三轴 MEMS 加速度传感器

一、功能概述 1.1 设备简介 本模块为了对电机、风机、水泵等旋转设备进行预测性运维而开发,只需一 个模块,就可以采集电机的 3 路振动加速度信号(XYZ 轴)和一路温度信号, 防护等级 IP67 ,能够适应恶劣的工…

aspose-words基础功能演示

我们在Aspose.Words中使用术语“渲染”来描述将文档转换为文件格式或分页或具有页面概念的介质的过程。我们正在讨论将文档呈现为页面。下图显示了 Aspose.Words 中的渲染情况。 Aspose.Words 的渲染功能使您能够执行以下操作: 将文档或选定页面转换为 PDF、XPS、H…

C++ 单一附合导线平差程序

一、以下图附合导线为例,图形如下: 二、第一步,读取测量数据,读取界面设计如下: 读取数据文本文件格式如下: (1)已知点坐标数据格式: (2)角度观测…

中仕公考:公务员和事业单位哪个更难?

公务员有稳定的职位和福利待遇,一直是众多求职者的选择,事业单位招聘也吸引着大量求职者,许多人都在纠结于公务员和事业单位考试应该怎么选择。 先来看看公务员考试,公务员考试主要包括国家公务员考试和省级公务员考试。国家公务…

vue3动态循环引入本地静态图片资源

解决方法一 根据官网的提示,我找到了最简单的方法,就是在将asset 前面加上src。 解决方法二 关于第二个方法,官网说:“实际上,Vite 并不需要在开发阶段处理这些代码!在生产构建时,Vite 才会进行…

Git命令窗口:创建一个.bashrc文件,别名实现git log (代替冗余的指令)查询提交修改日志功能

在我们的用户下创建一个.bashrc文件,然后添加如下代码。即可实现我们命令窗口由于每次想要看到好的效果而输入几条指令的问题。 这里我们就只需要使用 git-log 代替我们的git log。这样在命令窗口看到的效果就清晰明了。

在Android Studio中配置OpenCV

在Android Studio中配置OpenCV 1 下载OpenCV2 导入OpenCV模块3 修改配置4 增加依赖5 拷贝libopencv_java.so6 Activity中加入代码1 下载OpenCV 下载OpenCV的Android包并解压。 2 导入OpenCV模块 在Android应用中,导入OpenCV模块。 导入目录时选择Opencv Android中的sdk目…