摘要
性能关键型事务和存储系统需要快速持久化写入数据。通常,在永久存储器的数据路径上使用非易失性RAM(NVRAM),以便在系统确认写入请求之前临时且快速地存储写入数据。NVRAM通常由电池供电的DRAM实现。不幸的是,电池支持的DRAM体积小、成本高,占用了宝贵的DIMM插槽。在本文中,我们介绍了双字节和块可寻址固态驱动器(2B-SSD),这是一种新颖的NAND闪存SSD体系结构,旨在同时提供字节可寻址性和传统块可寻址性的双重视图。与传统存储设备不同,2BSDD允许通过两个独立的字节和块I/O路径访问同一文件。它通过直观的软件界面控制内部DRAM和NAND闪存之间的数据传输,并管理两个地址空间的映射。2B-SSD实现了在存储设备上访问文件的完全不同的方式和速度;应用程序可以使用内存映射I/O直接访问它们,而且还可以使用类似DRAM的延迟进行写入。为了量化2B-SSD的好处,我们修改了主要数据库引擎的日志子系统,将日志记录直接存储在其上,而无需将其缓冲在主机内存中。在运行流行的工作负载时,我们测量的吞吐量增益范围为1。2×2。8×无数据丢失风险。
1. 引言
几十年来,区块一直是大容量存储系统的数据I/O单元。所有的数据管理软件,包括操作系统,最终都针对block进行了优化,迄今为止开发的技术都是相关的,并且在这些天之前都运行得很好。内存层次结构trinity CPU高速缓存、DRAM和非易失性磁盘似乎仍然很强大,并且随着块的概念在其中根深蒂固而更加稳固。
现代数据管理和存储系统面临两个非常重要的技术趋势,然而,这迫使我们重新审视内存和存储层次结构的设计和实现实践。显然,第一个趋势是用NAND闪存固态驱动器(SSD)快速更换硬盘驱动器(HDD)。这种趋势在大型超规模数据中心和任务关键型企业存储平台中尤为明显。事实上,硬盘供应商开始从他们的产品中删除“高性能硬盘产品”。因此,为了克服特定于HDD的遗留优化带来的低效问题,我们做出了大量努力来修改操作系统和数据库算法以及存储I/O协议本身。
第二个趋势是对字节寻址、持久内存(PM)技术的重新关注。虽然现实的PM产品仍然不可用,但软件和硬件社区都在寻找新的策略,利用可字节寻址的PM来提高系统响应能力和功耗。目前与PM最接近的产品是非易失性RAM(NVRAM),它通常由DRAM、NAND闪存和电池支持的电源]组成。到目前为止,NVRAM一直是极少数高端企业存储服务器的选择,以加速用户数据和元数据的记录。新的PM技术有潜力修改当前的工作存储器和块存储二分法,消除DRAM和磁盘之间的(去)分段和数据转换。然而,由于许多原因,PM不太可能完全取代系统中的块存储。首先,目前PM的能力非常有限。大部分nvram只有4 ~ 16gb。而且,由于DRAM的访问延迟与PM之间存在差距,PM不太可能取代整个工作存储器。因此,NVRAM被用作一个非易失写缓冲区或一个小的低延迟存储设备,而不是取代整个内存和存储。
目前使用NVRAM的内存存储层次结构还有另一个限制。PM中的数据不能被块I/O访问,这在减少大数据传输的CPU开销方面有巨大的好处。这意味着PM中的数据应该通过整个I/O堆栈退级到永久存储。这种限制促使我们想到一种混合的持久存储,它既具有块可寻址接口,又具有字节可寻址接口的优点,同时消除了(去)分段操作和I/O堆栈开销。
幸运的是,今天的pcie附加NVMe ssd包含了正确的成分,帮助我们实现了混合持久存储的想法。这些成分是SSDinternal DRAM和PCIe互连的字节寻址能力。在这项工作中,我们提出了为现代NVMe ssd设计的2b - ssd及其内存管理api。据我们所知,这是第一个允许用户通过两个完全分离的数据路径(内存接口和传统(NVMe)块I/O)访问相同文件的SSD提议。通过它的api,文件中的任何字节都可以直接从应用程序中写入或读取,而无需在主机内存中进行缓冲。尤其值得注意的是,2B-SSD及其api以类似dram的延迟实现了数据持久性。实际上,我们演示了使用产品强度的2B-SSD实现,对于大小为1 KB或更小的写操作,可以实现亚1 μs的延迟。
为了实现这种新颖的SSD架构,我们采用了硬件/软件协同设计,同时提供了字节和块可寻址的双重视图。为了让内存接口的文件存储在SSD上,我们引入了一个内部数据路径之间的部分SSD内部DRAM和NAND闪存。我们首先实现一个地址转换硬件,它将指向内存映射I/O (MMIO)[21]地址的引用重定向到指向前者的地址。然后我们为这两者之间的映射编写固件。此外,为了防止意外的数据更新和确保一致性,即使存在两个独立的字节和块I/O路径,我们添加了一个硬件组件,阻止I/O请求到NAND页,目前映射到DRAM通过内存接口访问。最后,为了保证DRAM中数据在断电时的持久性,我们将DRAM转换为持久内存。我们用额外的电力电容器来支持它,并集成了对断电检测和恢复的硬件-软件支持。如果应用程序使用2B-SSD api定义这个NVRAM和NAND闪存之间的映射,则前者作为后者的缓冲区。因此,存储在NAND闪存上的数据可以通过内存接口访问,就像它们存储在一个快速的、字节可寻址的内存上一样。
因此,本文的主要贡献可以总结如下:
- 到目前为止,2B-SSD是第一个提供用两个分离的字节和块I/O路径访问相同文件的SSD方案,并已在一个商用NVMe SSD上实现。2g - ssd及其api允许通过内存接口直接从NAND闪存访问文件。特别值得注意的是,这两种方法都在高容量NAND闪存上实现了类似dram的写延迟(即100纳秒)。
- 为了更好地利用2B-SSD,我们重新设计了write-ahead logging(W AL)[22],并成功地将修改后的W AL移植到广泛部署的SQL和NoSQL数据库引擎上。为了减轻W AL因小的频繁更新而带来的性能损失,我们对其进行了修改,采用了2B-SSD api,以便它们的日志记录直接存储在SSD上,而不需要在主机内存中进行缓冲。
- 我们在一个真实的服务器平台上测量和报告应用程序级别的结果。当我们修改后的数据库引擎在2B-SSD上运行Linkbench[23]或YCSB[24]时,吞吐量增益在1.2×and 2.8×范围内,没有数据丢失的风险。
在本文的其余部分,我们在第二节通过讨论存储层次模型给出了这项工作的背景。在第三部分,我们描述了2B-SSD的总体架构和详细设计及其api。第四节介绍了2B-SSD概念如何帮助加快W AL处理的案例研究,然后是第五节的实验评价结果。第六节进一步讨论了我们的研究成果,第七节进一步讨论了相关工作。最后,第八节总结。
2. 背景
2.A 存储层次
1)传统的体系结构
- 计算机系统传统上有两个存储层次,主存储(如主存储器)。如图1(a)所示。一旦操作系统建立了虚拟到物理的地址映射,CPU对主存储的访问就通过硬件机制(如TLB)实现,而不需要软件干预。因为内存访问是最频繁的操作,主存储必须提供非常高的带宽和低延迟[25]。
- 另一方面,次要存储访问严重涉及软件协调。例如,Linux I/O堆栈包含一个复杂的结构,它由虚拟文件系统层、大量文件系统、块I/O层、I/O调度器、软件和硬件调度队列以及设备驱动程序组成。在进入设备硬件之前,一个I/O操作将在这些软件组件中走过许多步骤。I/O堆栈软件不断发展,以适应存储I/O功能和速度的进步。例如,最近的NVMe ssd[26]吹嘘到10×the的I/O率仍然流行的SATA 3.0 ssd。一种新型的低延迟NVMe ssd正在被引入[27,28]。为了从这些设备中获得尽可能好的性能,应用程序可以绕过操作系统内核,通过用户级驱动程序[29]直接访问存储设备。
2)持久性内存(PM)存储
- 在这种架构中,持久性是由CPU的主内存总线上的可字节寻址的PM存储媒体提供的(见图1(b))。提供了一些DRAM来服务内存访问,并捕获热工作和存储数据。要充分实现PM存储的好处,可能需要对存储系统和数据管理软件[30]进行重大的检查。利用PM存储的破坏性最小的方法是在其上构建块存储抽象,如图1(a)所示。在这种情况下,应用程序不需要更改,但它们可以快速和低延迟的块I/O。
- 在更集成的系统中,操作系统不再需要分别管理内存和磁盘中的数据结构,应用程序可以直接将数据存储在PM存储中,而无需首先在DRAM中缓冲数据。因此,在存储层次之间定位、传输和转换数据的I/O堆栈是不需要的。目前正在积极研究利用内存持久性的算法和系统支持[31-35]。尽管PM存储有一些好处,但它不太可能淘汰传统的块存储,因为NAND闪存,最便宜的持久固态存储器,正在不断地向垂直方向扩展[36]。
3)异构内存
- 如前所述,NAND闪存ssd预计将保持较长的寿命。其他重要的系统考虑事项有:(1)ssd(标准2.5英寸尺寸)可以现场使用,而内存则不行;(2) NAND闪存在写操作上的功耗要求比正在出现的持久内存候选[28]低得多,这在处理大数据集方面是非常重要的。
- 图1(c)给出了一个实际的架构,其中内存总线上提供一个相对较小的PM,而一个较大的块存储提供持久存储容量。在这种情况下,PM空间可以用于特定的目的,例如,从事务系统捕获延迟时间最长的关键数据。实际上,根据应用程序的性能[37],写操作的临界程度可能有很大的不同。像日志和日志提交这样的频繁的小写一直被认为是使用小PM进行优化的完美目标。在当今的高端存储和数据库平台中,PM通常使用电池支持的DRAM(或NVRAM)实现。1Microsoft SQL Server 2016采用了这种架构来加速日志记录,并获得了2×[20]的性能增益。已经提出并研究了该体系结构的其他用例[38-42]。
4)混合存储
- 具有有限PM(如NVRAM)的异构存储体系结构遇到了实际挑战。首先,NVRAM占用内存插槽,而内存插槽在大型内存服务器中是稀缺资源。更糟糕的是,每个通道的内存数量随着DRAM时钟速度[43]的增加而减少。另一方面,NVRAM是一个复杂的设备,有一个备份存储器(通常是NAND闪存),一个外部电池和支持电路。因此,NVRAM产品的价格是同等大小DRAM的2 ~ 3倍。
出于这些原因,我们提倡图1(d)所示的混合存储架构。在性能方面,混合存储体系结构类似于异构内存体系结构。混合存储体系结构中的字节寻址PM容量由SSD提供。对于像PCIe这样的现代I/O互连,这样做是可行的,因为它们可以公开一个可以用内存指令访问的地址空间。混合存储体系结构为软件提供了一个嵌入式PM存储,并相应地消除了PM中的数据通过厚重的I/O堆栈来实现持久性的需要。此外,它节省了一个DRAM内存插槽,并且是热插拔的——与NVRAM相比,系统中PM的总大小在运行时可以增加。我们将在第三节进一步深入研究这个架构。
2.B 字节可访问性的I/O互连
如上所述,为了实现混合存储体系结构,底层I/O互连必须能够为I/O设备的内存访问提供服务。例如PCIe[44]和CCIX[45]。2BSSD架构建立在PCIe之上,因为它是目前应用最广泛的I/O互连技术。但是请注意,该体系结构可以很容易地通过其他互连(如CCIX)来实现。接下来,我们将总结PCIe设备在典型平台上是如何识别的。
PCI设备(包括NVMe ssd)有一个由一组寄存器组成的“配置空间”。系统复位时,PCIe设备处于未初始化状态。在系统复位后的PCI枚举阶段,BIOS和操作系统会发现已安装的所有PCI设备,并通过读取其配置空间进行初始化。在配置空间寄存器中,基地地址寄存器(BAR)是设备如何发布它所需要的内存数量。一个PCI设备最多可以有6个32位的bar。
BIOS或操作系统读取给定PCI设备的每个BAR,并从系统内存映射中分配相应的地址窗口。注意,该地址范围不消耗主机上的物理内存,但仅用于地址解码。当MMIO[21]被用于这个特殊的内存范围时,一个对它的读/写将被发送到设备。设备负责将内部资源(如寄存器和内存)映射到主机可见的内存范围。例如,控制和操作NVMe SSD的寄存器是在BAR0地址范围[13]上定义的。
应用程序可以使用mmap()系统调用将这些内存映射到它们的用户空间,然后使用内存指令访问虚拟内存地址,该地址最终将被转换为PCIe设备提供的物理内存空间。这种方法是2B-SSD用来向CPU开放PM资源的机制。
3. 2B-SSD:设计与实现
本节将详细介绍2B-SSD。给定允许字节访问的I/O互连(在我们的例子中是PCIe), 2B-SSD的自然实例化是在NVMe SSD上叠加字节可访问性。我们首先描述基本架构,并解释其关键组件,以说明这是如何实现的。
3.A 体系结构
在NAND闪存SSD中,暴露内存接口并不简单。因为底层存储媒体不允许对存储数据的字节级读和写访问,所以不能简单地将媒体公开到内存地址空间。为了克服这个限制,我们在NAND闪存介质中使用内部DRAM作为数据缓冲区。2BSSD将内存访问从主机CPU重定向到ssd内部的DRAM,实现对文件的字节级访问。为此,它实现了一个内部数据路径之间的DRAM和NAND闪存。
2B-SSD的总体架构如图2所示。它有四个精心协同设计的硬件/软件组件:BAR管理器、BA-buffer2manager、读取DMA引擎和恢复管理器。BAR管理器支持一个额外的BAR用于字节颗粒文件访问,并管理从CPU到DRAM的内存访问重定向。BA-buffer实现了DRAM和NAND闪存之间的数据路径,并提供了控制api来管理这个DRAM缓冲区。读取DMA引擎有助于加速DRAM上相对较慢的内存读取。恢复经理负责备份和恢复2B-SSD的DRAM中的数据。在接下来的内容中,我们将详细描述每个组件。
1)BAR管理器
- BAR管理器要实现两个主要目标。首先,它打开了CPU可见的内存空间。为了做到这一点,它设置了BAR1,第二个BAR。通常,PCIe设备使用单个BAR(即BAR0)来进行设备操作。在2B-SSD中引入了BAR1,这样就专门为CPU准备了一个单独的内存空间,以便使用内存访问指令与2B-SSD通信。
- 其次,BAR管理器使用了一个地址转换单元(A TU),这是一种专门设计的硬件结构,用于连接暴露在CPU上的地址空间和2B-SSD内部DRAM中的内存空间。本质上,A TU实现了从/到PCIe接口的入站和出站地址转换窗口。BAR管理器利用A TU将对BAR1的内存范围的内存读或写重定向到DRAM中。从CPU的角度来看,它可以访问物理上由2B-SSD提供的DRAM容量。我们将在第iii - a4节中解释这个DRAM容量在断电时作为持久内存提供给CPU。
- 值得一提的是,主机系统必须认真对待2B-SSD的持久内存,才能获得良好的写性能。我们利用底层CPU[47]的写合并(WC)模式。通过在CPU的WC缓冲区(当前x86 CPU为64字节)中将单个写合并到更大的写突发中,可以显著减少内存访问。通过为WC保留BAR1的地址空间,我们的BAR管理器允许高速内存写入2B-SSD。
1) BA-buffer管理器
- BA-buffer管理器维护了DRAM和NAND闪存在2B-SSD中的内存层次结构。ba缓冲区是我们在DRAM中预留的用于构建持久内存的容量。BAbuffer驻留页面是从NAND闪存中缓存的页面。我们在软件中实现了ba缓冲逻辑,该软件运行在2B-SSD的ARM核心上。这个逻辑主要将ba缓冲区映射到一组NAND页面,并处理缓冲区和NAND页面之间的数据传输。
- DRAM地址与NAND闪存数据之间的映射信息存储在一个表中。如图2所示,每个表项包括(1)entry_id, (2) BA-buffer中的start_offset,(3)给定文件的start_lba和(4)length。ba缓冲区逻辑的操作是由一组主机端api显式编排的,因为BAbuffer属于主机地址空间。例如,调用ba_pin()将在DRAM地址(start_offset)和NAND闪存数据(start_LBA)之间建立映射,将NAND闪存数据(长度)复制到DRAM区域,并将映射信息存储在映射表中。因为主机CPU对BA-buffer(由硬件处理)的内存引用要比BA-buffer管理事件(由软件处理)频繁得多,所以软件开销很小。让我们在第III-C节进一步描述ba缓冲区管理api。
- BA-buffer管理api旨在使应用程序能够在BA-buffer上分配内存,并使用它们读写文件。在应用程序的内存读或写请求时,BA-buffer管理器将数据从NAND页面加载到BA-buffer,或将缓冲的数据刷新到相应的NAND页面。因此,2B-SSD上的任何NAND页面都可以通过两个完全分离的数据路径访问:内存接口(BA-buffer)和传统(NVMe)块I/O。注意,除非适当控制,否则使用两个独立路径访问同一个文件可能会导致持久化数据中的数据不一致。为了防止意外的数据更新并确保持久数据的一致性,BA-buffer管理器阻止对NAND页的I/O请求,这些NAND页目前映射到BA-buffer,以便通过内存接口访问。我们设计并利用名为“LBA检查器”的硬件逻辑来窥探每个I/O请求的LBA,以查看是否需要保护相应的NAND页面。
3)读取DMA引擎
- 如章节III-A1所述,ba缓冲区通过利用底层CPU的写组合来实现高的写带宽。相反,使用内存接口从ba缓冲区读取数据比使用块I/O命令读取数据要慢。例如,在ba缓冲区中读取4kb需要比同等块读取(150usvs.)多一个数量级。如图7 (a)所示。这是因为BA-buffer是一个“不可缓存”区域,所以从BA-buffer的读取被分成8字节的读取PCIe事务。
- 为了加速内存读取,2B-SSD利用了一个称为DMA引擎的DMA设施(图3)。2).该引擎可以卸载昂贵的内存操作,如将大数据从2B-SSD复制到主机指定的目的地。性能的提高来自两个方面,一是减少(ssd内)传输数据所需的CPU周期,二是利用专用的、独立的DMA设施提供的并发性。我们提供了一个直观的API来在用户应用程序中利用和集成读DMA引擎。sectionv - b中的实验结果表明,对2 KB或更大数据的读操作将从使用读DMA引擎中获得显著好处。
4)恢复管理器
- BA-buffer中的用户数据内容必须在断电时显示为持久的。然而,在物理意义上,ba缓冲容量是从易失性DRAM中提取的。我们设计了一个恢复管理器,把ba缓冲区变成一个持久内存。
- 现代NVMe ssd已经有了自己的失电保护子系统,包括失电检测电路和备用电力电容器[27,49]。我们的恢复经理以具有成本效益的方式利用这个子系统。首先,我们添加更多的电容的电源子系统2 b-ssd(见图6)。提供后备电源容量足以安全地保存BAbuffer内容和所有相关的信息(例如,BAbuffer映射表)在NAND闪存的保留区域2 b-ssd完全关闭。其次,编写了一个软件恢复逻辑,运行由功率损耗检测电路启动的数据保护程序。当电源恢复时,它从保存的区域恢复ba缓冲区内容和管理信息。
3.B 持久性保证
一旦存储在BA-buffer中,对2B-SSD的内存写操作就会变得持久。但是,在WC模式下,它们不会立即刷新到ba缓冲区。相反,它们首先缓存在底层CPU的WC缓冲区中,发送到PCIe根复合体,最后存储在ba缓冲区中。问题是,在这个写路径期间,它们被任意重排序为[41],并在WC缓冲区中缓存一段时间。后者尤其重要,因为在断电时,该CPU缓冲区中的数据将丢失。为了保证持久性以及强制这些内存写入的顺序,我们引入了两种类型的刷新和内存屏障支持,如图3所示。
-
WC缓冲器→根复合体:clflush(缓存线刷新)后跟MFENCE(内存围栏)[50]用于按顺序将WC缓冲区中的数据刷新到根复合体。clflushis是一条指令,用于强制刷新相关地址的缓存线,MFences会对所有加载和存储指令下订单。clflushis仅由MFENCE[51]订购,因此前者应紧跟后者。通过内存接口访问2B-SSD的应用程序可以使用这对指令来确保以前的存储包含在对根复合体的写回中。
-
根复合体→BA缓冲区:我们定义并利用一种称为“写验证读”的操作,在PCIe根复合体上强制执行写顺序和刷新。在PCIe系统中,根复合体将CPU和内存子系统连接到PCIe交换机结构,其中连接了一个或多个PCIe设备[44]。问题是,PCIe内存写入(例如,对2B-SSD的内存写入)变为“已发布”事务,不等待完成响应。在我们的设计中,我们通过从BA缓冲区读取零字节的内存来实现写验证读取操作。这是因为读和写事务在根复合体中是顺序化的,并且读访问是一个“未发布”事务,这确保了所有先前的写都被提交。
3.C 2B-SSD API
我们提供以下API,使BA缓冲区编程对应用程序开发人员来说非常简单。目前,API的功能是在2B-SSD的上下文中定义的,但尚未在NVMe标准规范中定义。在我们当前的设计中,我们利用Linuxioctlinfrastructure来实现API,以便2B-SSD API可以通过文件系统。
- BA_PIN(EID、offset、LBA、length):此API将NAND闪存中的页面带到BA缓冲区,将其固定,然后向BA缓冲区映射表添加一个新条目。请求的页面范围为LBA toLBA长度,可以是一个或多个4KB页面。收到此请求后,BA缓冲区管理器首先通过查找映射表来检查指定的范围是否与BA缓冲区缓存的数据重叠。如果没有,它会将数据从NAND闪存读入BA缓冲区中的给定FFSET。最后,它将带有BAONTOOFFSETT映射的第二个条目添加到映射表中。只有具有访问请求的LBA范围权限的应用程序才允许使用此API。否则,操作系统将阻止应用程序的尝试。
- BA_FLUSH(EID):给定LBA范围由第八个映射项引用的NAND闪存,此API将其在BA缓冲区中的状态与NAND闪存同步。也就是说,它将BA缓冲区中的所有内容传输到相应的NAND页面。我们执行此机制是因为2B-SSD API允许CPU直接访问BA缓冲区,而2B-SSD无法确定哪些数据脏或不脏。收到此请求后,2B-SSD将给定映射项引用的所有BAbuffer内容存储到NAND闪存中。如果操作成功,BA缓冲区管理器将从映射表中删除标识。
- BA_SYNC(EID):此API旨在确保BA缓冲区中内容的持久性。与上述两个API不同,它不需要从NAND闪存读取/写入NAND闪存,并且不会相应地改变映射表。此API按顺序执行三个子功能:(1)确定给定的第二个映射项引用BA缓冲区中的哪些页面,(2)针对指定的BA缓冲区页面发出CLFLUSH,然后是MFENCE,以及(3)向2B-SSD发送write-verify read命令。
- BA_GET_ENTRY_INFO(EID):给定anEID,此API显示映射表中第八个条目的详细信息。它由Basync(EID)在确定由长度映射固定的BA缓冲区页时使用。宿主应用程序还可以使用此API获取相应的映射信息。
- BA_READ_DMA(EID、dst、length):给定第八个映射项所指的BA缓冲区中的内容,此API利用2B-SSD的读取DMA引擎,并对其进行编程,以将最长长度字节的内容复制到从dst开始的范围中。当操作完成时,主机最终接收到来自2B-SSD的中断。
最后,图4显示了包括为2B-SSD开发的设备驱动程序的整个软件堆栈。此设备驱动程序提供初始化2B-SSD所需的功能。我们使用ioctl()和特定于SSD的供应商独特的命令工具来传递API,因此传统的块I/O路径没有变化(图4的左侧)。在2B-SSD API完成所有初始化后,主机应用程序可以通过MMIO(图4的右侧)访问BA缓冲区。
4. 案例研究:数据库日志
作为我们的案例研究,我们将重点放在SQL和NoSQL数据库系统上,因为它们的日志提交因频繁写入而臭名昭著。本节介绍如何修改数据库日志记录机制以利用2B-SSD的内存接口。2B-SSD还非常适合于文件系统日志记录和业务线应用程序,因为在这些应用程序中,关键的小写操作会损害应用程序的性能。
4.A 2B-SSD对日志的影响
WAL是数据库系统用于强制事务原子性和持久性的标准技术[22]。使用WAL时,所有数据库修改应在应用之前写入日志文件。问题在于,编写WAL日志会导致小的频繁写入,这意味着性能会显著下降。首先,尽管WAL日志通常比单个页面小得多(通常大小为4KB),但I/O大小应该与页面大小一致。此外,日志写入之后通常跟有fsync()函数,以保证立即持久性。此函数导致将设备缓存中的所有修改数据写入NAND页面。设备缓存中的某些数据可能与数据库系统无关,但它们应该等待SSD写入所有缓存数据。
2B-SSD使用其内存接口解决了日志提交的这一重大负担,其好处如下:
- 字节级读/写:2B-SSD使数据库系统能够以字节粒度将数据写入其NVRAM,这显著降低了传统SSD中的写入负担。对于NAND解决方案,使用合并内存吸收小的频繁写入尤其有效,因为NAND写入延迟可能更长,甚至与读取延迟相比差异极大,因为它们的读取/写入不对称[52]。
- 使事务持久化的低开销:传统SSD应该承担编程或擦除NAND页以进行写入的沉重负担,而2B-SSD不需要携带NAND页以进行数据持久化。一旦写入BAbuffer,在电容器的保证下,WAL日志将变得持久。它们的持久性只需要CPU缓存刷新,然后是写验证读取。与高NAND操作开销相比,这对指令的开销可以忽略不计。
- 降低写入放大系数(WAF)。所有日志都是按时间顺序排列并附加到日志文件中的连续记录。如本节所述,WAL日志通常比日志页小,数据库系统不会在存在部分填充的日志页的情况下创建日志页。因此,同一日志页可能会多次写入存储器。相反,在本例中,写入日志页的目标从NAND页更改为BA缓冲区。此外,填充WAL日志的多个页面会立即从BA缓冲区刷新到NAND页面。每个日志页的单个NAND写入减少了WAF[53],并优化了尾部延迟和SSD寿命。
4.B 针对2B-SSD的WAL实现
为了证明第IV-A节中描述的2B-SSD的有效性,我们为2B-SSD(BAWAL)提供了一个案例。这是一种新的WAL方案,旨在利用2B-SSD的字节可访问性。与传统的WAL方案不同,BA-WAL将WAL日志直接存储在2BSDD上,而不在主机内存中缓冲它们。2B-SSD提供了写入数据的快速持久性,并且很容易使日志提交脱离性能关键路径,这显著提高了数据库事务处理中的响应时间和吞吐量。
图5将提交模式与完成事务进行了比较。传统的WAL方案支持同步和异步提交模式[54],我们的BA-WAL方案提供了RSBA提交模式。同步提交以牺牲性能为代价确保数据持久性。在此模式下,数据库系统应等待所有日志刷新到永久存储器。相反,异步提交强调性能而不是数据丢失的风险,并在事务完成和所有日志持久化之间提供一个时间窗口。
与上述两个阶段不同,BA提交包括三个阶段;记录、提交和刷新。在日志记录阶段,数据库系统将所有日志附加到BA缓冲区。关键是,日志是尽可能多地编写的。在提交阶段,它们在BA缓冲区上标记事务的提交点兵调用BA_SYNC()。通过确保BA缓冲区中的所有日志变得持久,此阶段完成给定事务。最后,在刷新阶段,通过单个BA_FLUSH()调用将来自多个事务的一组WAL日志从BA缓冲区传输到固定的NAND页面。BA-commit是传统提交模式中最好的一种;它不仅实现了与面向性能的异步提交一样高的吞吐量,而且还确保了与同步提交一样强的持久性。2B-SSD的快速持久性主要促成了这一改进。WAL日志一旦写入BA缓冲区,就会变得持久,这样数据库系统就可以在持久WAL日志真正提交事务后完成事务。
下面是在数据库引擎中实现BA提交的详细示例。为了隐藏刷新延迟,我们采用了“双缓冲技术”,以便日志记录和刷新阶段可以并行进行。WAL日志被附加到BA缓冲区的一半,而另一半中的日志被刷新到文件中。刷新后,日志子系统重新固定一半,以便BA缓冲区可用于接受新日志。
- PostgreSQL的BA-WAL。PostgreSQL[55]是一个开源、标准兼容的关系数据库系统。它包括一个名为dxlog的日志子系统,其中日志文件存储为一组段文件,每个段文件的大小通常为16MB。我们选择了最新版本的PostgreSQL(9.6.0),并修改了XLOG以直接使用2B-SSD API。具体来说,我们(1)将日志段文件的大小设置为BA缓冲区大小的一半以进行双缓冲,(2)将BA缓冲区映射到PostgreSQL的用户地址空间,并将其日志缓冲区分配给BA缓冲区,(3)禁用对日志段文件的块I/O写入,以及(4)执行钉扎和刷新(即BAPIN()和baflush())在事务处理过程中,我将进行并行处理。
- RocksDB的BA-WAL。RocksDB[56]是Facebook开发的嵌入式持久键值存储。它的三个基本结构是内存驻留MemTable、nSST文件(排序字符串表)和日志文件。新插入的数据存储在memtable(当它变满时将刷新为SST文件)和相应的日志文件中。崩溃时,它可以恢复反映到其日志文件中的memtable状态。RocksDB最多可建立两个memtables和日志文件,一个用于存储新数据,另一个已满并刷新到存储设备。与PostgreSQL类似,2B-SSD API用于为RocksDB实现BA-W AL,并应用了双缓冲。我们选择了版本5。1.RocksDB的第4部分,并重写其W-AL相关的可写文件类。重写类的构造函数现在创建一个新的日志文件,并将其LBA固定到BA缓冲区。每个日志文件都设置为BA缓冲区大小的四分之一,因为BA缓冲区的一半应该保留用于双缓冲。它的appendfunction也被重写,以使用memcpy()而不是块I/O将所有日志附加到BA缓冲区。
- Redis的BA-WAL。Redis[57]是一种开源的内存键值存储,用作持久数据库或缓存。它使用单线程设计,并按顺序为请求提供服务。作为主要的持久性选项,它使用一个只附加文件(AOF),记录系统接收到的每个写入操作。我们选择了版本3。2.使用2B-SSD API修改了AOF子系统。具体来说,我们(1)将AOF的大小设置为与BA缓冲区大小相同,(2)重写AppendFunction以使用memcpy()将所有日志附加到BA缓冲区,以及(3)在事务期间执行固定和刷新。在这种情况下,我们没有应用双缓冲,以避免违反Redis的单线程设计概念。
5. 评估
6. 讨论
根据我们的结果和经验,我们提出了一些观察、发现和评论。
启用内存接口的开销
- 2B-SSD需要一个集成DRAM和设备级NVRAM的电容器。目前,2B-SSD利用了SSD内部DRAM的一部分,这部分内存没有被承载SSD的普通固件所使用,并且8 MB的NVRAM可以以很小的额外成本提供备用电源电容器。即使使用这种小型NVRAM,通过充分利用NVRAM和NAND闪存之间的内部数据路径,即双缓冲机制,我们可以实现显著的性能提升。如图8所示,NVRAM和NAND闪存之间的最大内部带宽是在NVRAM大小约为8mb时实现的。更大的NVRAM容量可以提供更多的可用性,并减少ebaflush()开销,但我们并不期望更好的性能。我们还设法让2B-SSD的占用空间尽可能小;内部数据路径的额外二进制大小只有4.09 KB。通过最小化设备内资源的使用,我们保证即使在启用内存接口时,块I/O也不会降低性能。
2B-SSD是否适用于所有人?
- 并非所有应用程序都能从2B-SSD的内存接口中受益,但它们应该满足一些条件。首先,它们的数据必须需要足够小的字节粒度写入和大容量读取。这种类型的数据无处不在(例如,日志、日志和来自物联网设备的微小数据),并在它们的系统中不断累积。在许多情况下,这些数据是实时存储的,只有在需要时才通过批处理读取。我们确认较小的写大小比较大的写大小显示更好的性能增益。其次,它们必须是延迟关键,而不是带宽关键。如果一个带宽密集型的应用程序利用了2BSSD的内存接口,带宽就会被内部数据路径独占,这样其他使用块I/O访问的应用程序就无法获得足够的带宽。
- 此外,我们看到了将2B-SSD应用于大容量写和小容量读工作负载的机会,这与上面的情况相反。块I/O的强大带宽是写大容量数据的最完美的方式,通过预加载(固定)从NAND闪存到2B-SSD的NVRAM,读延迟可以非常好,如图7(a)所示。应用程序不需要读取整个页面来获取几个字节,以便节省DRAM或其他资源。
字节和块之间统一的数据结构
- 在2BSSD中,ba缓冲区上的数据以最初写入的格式传输到NAND闪存。通常情况下,WAL日志和日志无需重新格式化即可编写,只需要构建页面即可。然而,当擦除编码或加载发生时,用户数据需要在字节和页之间进行某种形式的转换。这是普遍应用2B-SSD的一个明显障碍。为此,应该支持存储内计算[61]。然而,在图1(b)所示的PM存储时代,我们预计这种块和字节的异质性将因此而减少。
7. 相关工作
众所周知,确保数据持久性的技术,如预写日志记录、日志记录[62]和阴影分页[63]会导致性能关键的写操作。学术界和工业界早就意识到他们的日常开支,并试图用电池支持的NVRAM来满足他们的紧迫性。
最近的一些先前的工作利用了正在出现的PM,如相变存储器,并提出数据库引擎直接在PM中缓冲区W AL日志,而不是在DRAM中[41,60,64,65]。通常假设异构内存体系结构(如图1(c))。但是请注意,如第二节所述,对PM缓冲区的日志写入是临时的,应该定期通过厚I/O软件堆栈写入永久存储。相比之下,2B-SSD促进了图1(d)的字节寻址存储,并直接永久地存储W AL日志,不需要任何I/O堆栈的干预。
最近有两项工作可以与我们相媲美,它们将NVRAM集成到SSD中。首先,Kang等人[66]buildDuraSSD,一种配备了类似我们的备用电容的SSD。他们修改了MySQL,以便在嵌入式DRAM中缓冲修改过的数据页,而不是在NAND闪存中。这将使数据库系统从频繁调用frequentfsync()的负担中解脱出来,从而保证数据的持久性。虽然DuraSSD将NVRAM区域暴露给应用程序,但它与2BSSD有根本的不同,因为DuraSSD的NVRAM只能通过块I/O堆栈访问。相比之下,2B-SSD允许应用程序通过内存指令直接写入NVRAM。
其次,NVMe SSD社区进行了标准化工作,定义了“持久内存区域(PMR)”特性[67]。与2B-SSD类似,PMR公开了ssd内部NVRAM的一部分,以便以字节粒度访问。然而,这两者之间有一个关键的区别。启用pmr的NVMe SSD不提供可互换的字节和块访问接口。它的NVRAM和NAND闪存之间没有内部数据映射和传输路径。因此,它们之间的数据传输应该通过主机I/O堆栈。相比之下,2B-SSD将NVRAM映射到NAND闪存,并通过内部数据路径高效地传输数据。
8. 总结
本文描述了一种字节和块可寻址的固态硬盘(2BSSD)的动机、设计和实现。我们还详细介绍了它新颖的软硬件接口。到目前为止,这项工作是第一个在SSD中公开可互换的字节级和块级访问接口的提议和全面实现。通过它的api,应用程序可以在2B-SSD上读写任意数量的字节,而无需将数据缓冲到主机内存中。我们的设计在SSD上实现了类似于dram的写延迟。我们的结果是,主要数据库引擎可以看到高达2.8×without的吞吐量增益,数据丢失的风险。2B-SSD允许这些应用程序免费享受昂贵的NVRAM带来的好处,而无需消耗宝贵的内存插槽。随着ssd成为提供交互应用的大型数据中心的默认存储设备,拟议的2B-SSD架构有潜力在不增加基础设施成本的情况下提高这些应用程序的响应速度。