High-Performance I/O for High-Performance Storage Engines

  1. 研究背景
    文章的研究背景是现代NVMe存储技术的发展,特别是基于闪存的NVMe SSDs(固态硬盘)的低成本和高吞吐量特性。这些设备通过PCIe/NVMe接口提供了前所未有的存储吞吐量,单个SSD能够实现超过一百万的随机IOPS(每秒输入/输出操作数)和7 GB/s的带宽。文章指出,尽管硬件性能显著,现有的数据库系统和存储引擎却只能利用这一性能的一小部分。研究背景强调了存储硬件的进步以及现有系统未能充分利用这些硬件能力的问题。

  2. 研究发现与问题解决
    文章提出的研究发现包括:

    • 通过I/O优化的存储引擎设计,可以缩小硬件和软件之间的性能差距。
    • 在大量数据超出主存的重负载情况下,新系统设计能够实现每秒超过100万次的TPC-C(事务处理性能委员会)事务处理。
    • 确定了4 KB页面大小是在随机IOPS、吞吐量、延迟和I/O放大之间取得最佳折衷的方案。
    • 通过实验研究,发现使用现代NVMe存储设备时,CPU周期非常紧张,需要对存储引擎进行优化以充分利用硬件能力。

    文章解决的问题是如何设计一个高性能的存储引擎,使之能够充分利用现代NVMe存储硬件的性能,尤其是在面对大量数据超出主存时的性能问题。

  3. 技术点设计思路

    • I/O优化:文章提出了一种针对I/O的存储引擎设计,包括高效的缓冲池、文件系统绕过使用O_DIRECT和fsync批处理等技术。
    • 页面大小选择:研究了不同页面大小对性能的影响,并选择了4 KB作为最优页面大小。
    • 并行性管理:采用了合作式多任务调度,使用户空间线程能够高效地处理并发请求,同时减少上下文切换开销。
    • 异步I/O:为了避免阻塞I/O请求导致的性能问题,设计了使用非阻塞I/O接口的系统,允许工作线程异步提交I/O请求。
    • 后台任务作为系统任务:将后台任务(如页面置换)作为系统任务运行在工作线程上,避免了专用后台线程的需求,并提高了效率。
    • 统一I/O抽象:实现了一个支持所有主要异步I/O库(如libaio、io_uring和SPDK)的I/O后端,并提供了一个低开销的RAID0抽象。
    • CPU优化与可扩展性:对LeanStore进行了优化,包括移除全局锁、使用分区锁、优化页面置换策略和内存分配,以提高系统在高IOPS下的可扩展性。

这些设计思路和技术点共同构成了文章提出的存储引擎设计,旨在充分利用现代NVMe存储的性能潜力。


正文部分

摘要

基于flash的NVMe SSDs非常的便宜并且提供很高的吞吐量。将这种设备组合到一台服务器中,可达到每秒至少1000万次I/O操作。我们的实验表明,现有的 外存数据库系统 和 存储引擎 没有充分利用这一性能。在这项工作中,我们证明可以通过设计 基于I/O优化的存储引擎 来缩小硬件和软件之间的性能差距。在内存严重不足的环境配置中,数据集比主存大10倍,而我们的系统每秒可以实现超过100万次TPC-C事务。

引言

闪存(flash)的性能。在过去十年里,闪存固态硬盘(flash SSDs)取代了磁盘,成为操作数据库系统的默认持久存储介质。最近,SATA接口已经被PCIe/NVMe接口所取代,该接口解锁了前所未有的存储吞吐量:使用4个PCIe 4.0通道,单个SSD可以实现超过每秒100万次随机I/O操作(IOPS)和7 GB/s的带宽。由于现代通信服务器每个插槽最多128个PCIe通道,因此单插槽服务器可以在全带宽下轻松托管8个或更多SSD。存储带宽不断增加的趋势将继续:具有PCIe 5.0的服务器已经可用,并且已经宣布了每个设备具有相应的12 GB/s的SSD。这意味着NVMe SSD的阵列正接近DRAM的带宽

闪存(flash)容量。SSD不仅有很高的吞吐量也很便宜:在DRAM价格停滞了十年,闪存价格迅速下降之后,企业级SSD每TB的成本不到200美元,比DRAM便宜约10-50倍。我们可以通过一个例子来解释这个:我们一共有15000美元的服务预算,只需一半的预算,就可以配置一个合理的服务器,例如64核CPU、512 GB RAM和快速网络。剩余的预算可以投资于额外的DDR4 RAM模块或PCIe 4.0 NVMe ssd,导致以下两种配置:
在这里插入图片描述
这些配置表明,将更多的钱花在ssd上而不是RAM上可以获得更大的容量(32 TB而不是2.5 TB)。公共云提供商也观察到了这一点:AWS提供8个(i3en)实例,Azure提供10个实例
(Lsv2) NVMe闪存盘。鉴于Optane等替代存储技术没有取得商业成功并因此停产,我们认为闪存仍将是以经济高效的方式存储大型数据集的唯一可行选择

**现有系统的性能差距。**就其基本体系结构而言,用于闪存的DBMS类似于基于磁盘的设计:它们依赖于缓冲池缓存、基于页面的存储和B树或LSM树做索引。几个现代存储引擎,包括RocksDB和我们的LeanStore系统都明确声称是针对闪存进行优化的。但是,如图1所示,现有的内存不足系统无法利用现代NVMe阵列的性能。在实验中,我们在64核AMD服务器上使用8块三星PM1733固态硬盘对5个系统的性能进行了简单的随机读取基准测试。(注:“out-of-memory” 在计算机科学领域通常指的是一种情况,即计算机的内存不足以执行当前的任务或程序。在这段文本中,它可能指的是现有的系统无法充分利用现代NVMe存储阵列的性能,因为它们在处理超出内存容量的数据时遇到了限制。因此,这里的 “out-of-memory” 可以翻译为 “内存不足” 或 “超出内存”。)根据说明,这些ssd中的每一个每秒可以执行1.5M随机4 KB读取,因此对于这个简单的工作负载,可以期望实现8×1.5M=12M查找/s。事实上,我们发现最好的系统只能达到3.6 M查找/s——3.5倍的差距。对于更复杂和写密集型的TPC-C,我们发现与现代的TPC-C相比有更大的4.7倍的性能差距NVMe驱动器能做什么,以及现有系统能做到什么。正如我们在本文中所展示的,充分利用闪存需要仔细地与闪存NVMe ssd共同设计存储引擎。

**研究问题和论文提纲。**我们缩小这一性能差距的高级目标可以分解为以下研究问题:

  • Q1:NVMe ssd阵列能否达到硬件规格中承诺的性能?
  • Q2:应该使用哪个I/O API (pread/pwrite, libaio, io_uring) ?是否有必要依赖于内核绕过(SPDK)?(什么是SPDK
  • Q3:存储引擎应该使用哪种页面大小来获得良好的性能,同时最小化I/O放大?
  • Q4:如何管理高SSD吞吐量所需的并行性?
  • Q5:如何让存储引擎足够快,能够管理数千万IOPS?
  • Q6:I/O应该由专用的I/O线程执行还是由每个工作线程执行?
    为了回答这些问题,我们首先在第2节中对NVMe闪存的硬件特性进行了实验研究。
    基于这些发现,我们推导出高性能存储引擎的含义。然后,第3节给出了一个可以充分利用NVMe阵列的I/O后端蓝图。

**系统集成和技术。**我们将本文中提出的技术集成到LeanStore中,这是一个开源存储引擎原型。LeanStore在设计时考虑了ssd,并且已经应用了早期工作中推荐的几个重要的I/ o相关优化,包括快速缓冲池,使用O_DIRECT绕过文件系统,以及fsync批处理。这个基线版本是本文的起点,足以利用单个NVMe SSD,但是,如图1所示,不能利用8个NVMe SSD

前所未有的性能 新版本的LeanStore是第一个能够完全缩小这一差距的系统。诚然,我们的技术比全新的技术设计得更仔细,但它们结合在一起,产生了一个实用的系统设计,配置参数很少,实现了前所未有的内存不足性能。我们也相信本文的发现和技术适用于大多数其他存储引擎和数据库系统。

结果 我们在第4节中评估我们的设计。在一个服务器上64核和8个ssd,最终的系统在随机查找工作负载下确实实现了每秒12.5 M次查找。在具有400 GB缓冲池和4 TB数据集的更具挑战性的TPC-C基准测试中,LeanStore每秒执行超过1 M个TPC-C事务。对于20 TB的数据集,我们仍然可以实现0.4 M事务/s。对于所有工作负载,如果有足够多的并发用户请求,机器就会变成I/O绑定——正如人们所期望的那样,数据集比缓冲池大得多。

当代的NVME存储可以用来做什么?

在本节中,我们将介绍一系列微基准测试的结果,这些测试为我们提供了有关如何充分利用现代存储的必要背景知识。所有实验均在64核AMD Zen 4服务器上进行,并配有8 × 3.8 TB三星PM1733固态硬盘。关于实验硬件和软件设置的详细信息可以在4.1节中找到。

驱动的可伸缩性

驱动器可伸缩性。 根据硬件规格表,我们的三星PM1733固态硬盘能够执行每秒1.5 M的I/O操作(IOPS),随机读取4kb。因此,与8个驱动器,我们应该实现12 M IOPS的惊人数字。图2显示,吞吐量确实与所使用的驱动器数量完全一致。我们实际上实现了比预期稍微多一点,即每个SSD 1250万IOPS或1.56万IOPS。

读/写混合。 事务式工作负载通常是写密集型的,而且众所周知,ssd具有非对称的读/写速度。如图2b所示,在空SSD上随机写入,我们的硬件设置实现了47M IOPS。请注意,SSD的写入性能取决于SSD的内部状态和写入持续时间。在完整SSD和长时间写入的最坏情况下,吞吐量将会更低;数据表指定了最坏情况下,每个驱动器在135 k IOPS下的随机写入吞吐量。对于OLTP系统,混合读/写工作负载更为常见。如图2b所示,在10%(25%)写数时,我们测量了8.9 M(7.0 M)IOPS。这些微基准测试表明,现代NVMe存储为事务性系统提供了良好的基础,而事务性系统通常需要许多随机的I/O操作。

4KB页的情况

页面大小权衡。 与字节寻址的持久内存相比,对flash的访问发生在页面粒度。许多数据库系统使用更大的页面大小,如8 KB(PostgreSQL、SQL Server、Shore-MT)、16 KB(MySQL、LeanStore),甚至32 KB(WiredTiger)作为默认值。在LeanStore中,我们观察到,对于内存中的工作负载,较大的页面大小通常会提高性能,这就是为什么我们最初选择16 KB的[26]的原因。更大的页面大小的第二个好处是,它减少了缓冲区池中不同条目的数量,从而减少了缓存管理开销。然而,大页面的大缺点是内存不足工作负载的I/O放大。例如,对于16 KB的页面,读取或写100字节的记录会导致I/O放大160×。较小的4 KB的页面大小可以减少4×的扩增。
最好是选择小一点(但不要太小)。 对于数据中心级的ssd,我们发现页面大小的最佳位置是4 KB,因为它允许最高的随机读取性能和最低的延迟。图3显示,通过4 KB的页面和随机读取,可以实现几乎完整的带宽(6 GB/s)。这仅比使用较大的页面(或顺序访问)可以实现的6.5 GB/s的最大带宽慢8%。查看图3中不同页面大小的延迟,可以观察到延迟通常随着页面大小的增加而增加,其最小值为4 KB。从技术上讲,NVMe甚至允许更小的页面——多达512个字节。对于写放大,这将会更好,但我们的结果显示,使用比4 KB更小的页面会显著降低性能1。事实上,更小的页面大小实际上会导致我们的ssd上更糟糕的IOPS和延迟,如图3所示。这是由于flash转换层的更高开销,以及flash硬件内部没有为512字节页2进行优化。我们认为,从较低的延迟和I/O放大中获得的收益使4 KB页面成为优化内存不足p的系统的最佳选择。

SSD并行性

SSD并行性。 在内部,ssd是高度并行的设备,有多个通道连接到独立的闪存盘。向SSD获取足够的I/O请求可能会很困难,因为它需要大量的同步请求才能获得高性能。闪存随机读取延迟约为100微秒,比磁盘快100×,但仍然比DRAM慢1000×。对于同步访问(即,只有在前一个I/O请求完成后才发送一个新的I/O请求),这将导致微弱的10k IOPS(或40 MB/s)。因此,为了从ssd中获得良好的吞吐量,我们必须通过异步调度许多并行的I/O请求来利用它们的内部并行性。图4显示了IO-深度,即所有8个ssd上同时未完成的I/O请求的数量与总吞吐量之间的关系。我们可以看到,大约1000个并发I/O请求,即每个设备超过100个,需要获得良好的性能,以及3000个需要完全饱和系统。利用NVMe阵列的数据库系统面临的主要挑战之一是管理这些大量的I/O请求。

I/O接口

现代操作系统为存储I/O提供了多个接口。在这里,我们将讨论Linux上最常见的I/O库。最后,所有接口最终都对NVMe驱动器做同样的事情:接受I/O请求,并将它们放到主机系统用于与ssd通信的NVMe提交队列中。当SSD完成任何请求时,它都会将完成事件写入完成队列,如果使用了中断,则通知主机。这些库在如何提交请求和如何获取已完成的操作方面存在差异。

阻止POSIX接口。 在Linux上进行I/O的最经典的和最常见的方法是使用POSIX系统调用,如pread和pwrite。用于文件操作的POSIX调用通常以阻塞的方式使用,即每次提交单个I/O请求。然后,内核将阻止用户线程,直到请求由驱动器处理为止。这一点如图5a所示。
libaio: 传统的异步接口。libaio是一个异步I/O接口,它允许通过一个系统调用提交多个请求。这节省了用户模式和内核模式之间的上下文切换,并允许单个线程同时执行多个I/O操作。如图5b所示,I/O请求通过io_submit()以非阻塞方式提交,io_submit()立即返回,程序必须使用get_evenst()轮询完成情况。

第二部分未完待续


如何利用NVME存储:一个i/o优化的存储引擎设计

利用NVMe数组。 在本节中,我们将描述一种能够充分利用现代存储设备潜力的存储引擎设计。作为我们的起点,我们使用了LeanStore的基线版本。如图1所示,这个版本的LeanStore比其他系统更快,但不能充分利用NVMe阵列。请注意,简单地切换到4 KB页面和单独轮询I/O并不会取得什么效果,因为它会立即遇到软件瓶颈。高内存不足的性能需要对整个系统进行更改。
平行论是问题所在。 在高层,我们面临的主要挑战是现代硬件的并行性:首先,我们在请求级别有并行性,它可能直接来自用户查询,也可能来自DBMS本身(例如,通过查询内并行性或预取)。其次,我们有几百个或数百个,而不是数千个现代服务器的CPU核。第三,我们有1000+个I/O操作,使ssd保持忙碌。

设计概述和大纲

解决方案是在系统的每个部分都包含并行性。图7显示了我们的系统的高级视图及其必须处理的并行性。在图中从左到右,我们可以看到一切都从并发请求开始。为了管理所有这些请求,我们采用了协作多任务处理,其中由DBMS在用户空间中安排任务,如第3.2节所述。所有这些I/O请求最终会导致对免费页面的非常高的需求(例如,图中的8个M/s)。必须通过一个有效的页面替换算法和异步脏页写入来满足这个需求。在第3.3节中,我们认为这些cpu密集型的任务应该集成到工作线程中。最后,I/O后端使用前面介绍的I/O库之一,将DBMS与存储硬件连接起来。第3.4节讨论了如何将工作人员请求连接到硬件的几种模型。所有这些工作都是由有限数量的CPU内核并行完成的。由于总体的CPU预算是有限的,因此所涉及的每个组件都必须以可伸缩的方式进行大力优化和实现。这些优化将在第3.5节中进行描述。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值