AnyKey: A Key-Value SSD for All Workload Types
TL;DR 精炼摘要
本文提出了AnyKey,一种新型键值对固态硬盘(KV-SSD)设计,旨在解决现有KV-SSD在较大键的工作负载下性能下降的问题。通过优化元数据的大小,AnyKey在多种不同类型的工作负载中表现优于当前先进的KV-SSD设计。
摘要
Key-value solid-state drives (KV-SSDs) are considered as a potential storage solution for large-scale key-value (KV) store applications. Unfortunately, the existing KV-SSD designs are tuned for a specific type of workload, namely, those in which the size of the values are much larger than the size of the keys. Interestingly, there also exists another type of workload, in practice, in which the sizes of keys are relatively large. We re-evaluate the current KV-SSD designs using such unexplored workloads and document their significantly-degraded performance. Observing that the performance problem stems from the increased size of the metadata, we subsequently propose a novel KV-SSD design, called AnyKey, which prevents the size of the metadata from increasing under varying sizes of keys. Our detailed evaluation using a wide range of real-life workloads indicates that AnyKey outperforms the state-of-the-art KV-SSD design under different types of workloads with varying sizes of keys and values.
思维导图
论文精读
中文精读
1. 论文基本信息
1.1. 标题
AnyKey: A Key-Value SSD for All Workload Types (AnyKey: 一种适用于所有工作负载类型的键值对固态硬盘)
1.2. 作者
- Chanyoung Park (汉阳大学)
- Jungho Lee (汉阳大学)
- Chun-Yi Liu (美光科技公司)
- Kyungtae Kang (汉阳大学)
- Mahmut Taylan Kandemir (宾夕法尼亚州立大学)
- Wonil Choi (汉阳大学) - 通讯作者
1.3. 发表期刊/会议
未明确提供,但从 ACM Reference Format 和提供的 CCS Concepts、Keywords 推断为 ACM 旗下的会议或期刊。
1.4. 发表年份
2025年 (根据 Published at (UTC): 2025-02-06T00:00:00.000Z 判断)
1.5. 摘要
键值对固态硬盘 (Key-Value Solid-State Drives, KV-SSDs) 被认为是大型 键值存储 (Key-Value, KV) 应用程序 的潜在存储解决方案。然而,现有的 KV-SSD 设计通常只针对特定类型的工作负载进行优化,即那些 值 (values) 的大小远大于 键 (keys) 的工作负载。有趣的是,在实际应用中也存在另一种 键 (keys) 大小相对较大的工作负载类型。
本文重新评估了当前 KV-SSD 设计在这些未被充分探索的工作负载下的性能,并发现它们的性能显著下降。通过观察到性能问题源于 元数据 (metadata) 大小的增加,本文提出了一种新颖的 KV-SSD 设计,名为 AnyKey。AnyKey 的核心思想是防止 元数据 大小在 键 大小变化时无限制地增长。
通过对各种真实工作负载的详细评估,结果表明 AnyKey 在不同类型、不同 键 和 值 大小的工作负载下,均优于 最先进的 (state-of-the-art) KV-SSD 设计。
1.6. 原文链接
/files/papers/6916de05110b75dcc59adfbc/paper.pdf (该链接指向论文的 PDF 文件,状态为已发布。)
2. 整体概括
2.1. 研究背景与动机
-
核心问题: 传统的
块存储 (block-based)固态硬盘 (SSDs)在处理键值存储 (KV store)应用时,需要复杂的软件栈,导致延迟 (latency)高、主机 (host)系统CPU和内存开销大。为了解决这些问题,键值对固态硬盘 (KV-SSDs)应运而生,它将KV存储功能直接集成到SSD设备内部,旨在提供更低的延迟、更好的可伸缩性以及更高效的SSD管理。 -
当前挑战与空白: 尽管
KV-SSDs潜力巨大,但其普及和商业化应用仍面临挑战,主要原因是其性能通常仍落后于依赖主机丰富资源的主机 (host-based)KV存储。现有KV-SSD设计,特别是主流的基于日志结构合并树 (LSM-tree)的设计(例如PinK),主要针对高值键比 (high value-to-key ratio, high-v/k)的工作负载进行优化,即值 (value)远大于键 (key)的场景。这些设计在键相对较小的假设下,能够将元数据 (metadata)保存在设备内部动态随机存取存储器 (device-internal DRAM)中,从而实现高性能。 -
未探索的工作负载: 然而,在实际应用中,存在大量
低值键比 (low value-to-key ratio, low-v/k)的工作负载,其中键 (key)的大小相对较大。例如,社交图 (social graph)的对象元数据 (object metadata)或去重引擎 (deduplication engine)的数据库 (DB)等。这些low-v/k工作负载的特性导致元数据的总大小急剧增加,超出了SSD内部DRAM的容量限制,迫使元数据溢出到速度较慢的闪存 (flash)中。一旦元数据需要从闪存读取,每次键值对查找都会产生额外的闪存访问 (flash accesses),导致尾延迟 (tail latency)显著增加和输入输出操作每秒 (IOPS)急剧下降。 -
论文切入点与创新思路: 论文的切入点正是揭示现有
KV-SSD设计在low-v/k工作负载下的性能瓶颈,并提出一种通用设计来解决这个问题。其创新思路在于重新设计KV-SSD的元数据管理机制,使其在键大小变化时,元数据大小不会无限增长,确保元数据能够始终驻留在DRAM中,从而提升所有类型工作负载下的性能。
2.2. 核心贡献/主要发现
本文的主要贡献体现在以下几个方面:
-
揭示
低值键比 (low-v/k)工作负载的挑战: 首次全面揭示了一系列真实世界中低值键比的键值对 (KV)工作负载,并发现现有KV-SSD设计(以PinK为代表)在这种工作负载下性能显著下降。这些性能退化主要是由于元数据大小随着键相对大小的增加而急剧膨胀,无法完全驻留在SSD内部DRAM中,导致额外的闪存访问。 -
提出
AnyKey设计优化low-v/k工作负载: 针对low-v/k工作负载的性能问题,提出了名为AnyKey的新型KV-SSD设计。AnyKey的核心思想是最小化元数据的大小,使其能够适应SSD内部DRAM。这通过以下方式实现:- 将
KV对以排序组的形式存储在数据段组 (data segment group)中,元数据只需为每个组而非每个KV对维护一个键。 - 引入
哈希列表 (hash lists)作为新的元数据类型,在DRAM中存储键的哈希值,从而在实际读取闪存页面之前快速检查键值对是否存在。 - 通过这些优化,
AnyKey在low-v/k工作负载下,95th百分位尾延迟 (95th percentile tail latencies)平均提升56%,输入输出操作每秒 (IOPS)提升299%,并且显著延长了设备寿命。
- 将
-
提出 增强版以支持所有工作负载: 进一步提出了
AnyKey的增强版本 ,通过改进日志触发压缩 (log-triggered compaction)机制,避免了在高值键比 (high-v/k)工作负载下可能出现的压缩链 (compaction chain)问题,从而提高了日志结构合并树 (LSM-tree)的管理效率。- 能够为
high-v/k工作负载提供显著的IOPS提升,平均比PinK高15%。 - 综合来看, 在所有类型的工作负载下(无论是
low-v/k还是high-v/k)都优于最先进的 (state-of-the-art)设计PinK,实现了对low-v/k工作负载315%的IOPS提升和对high-v/k工作负载15%的IOPS提升,展现了其普适性。
- 能够为
3. 预备知识与相关工作
3.1. 基础概念
-
键值对固态硬盘 (Key-Value Solid-State Drives, KV-SSDs):一种新型的固态硬盘 (SSD)设备,它将键值存储 (Key-Value store, KV store)的功能直接集成到SSD内部,允许应用程序直接向设备发出键值对请求。与传统的块设备 (block device)SSD相比,KV-SSDs旨在简化软件栈、降低主机 (host)系统开销、提高吞吐量 (throughput)和设备寿命 (device lifetime)。 -
键值存储 (Key-Value store, KV store):一种非关系型数据库,其中数据以键 (key)和值 (value)的形式存储。每个键都是唯一的,并用于检索关联的值。KV store广泛应用于大型分布式系统和云服务 (cloud services)中。 -
日志结构合并树 (Log-Structured Merge-tree, LSM-tree):一种为写密集 (write-intensive)工作负载优化的磁盘数据结构。它的核心思想是所有写入操作都是非原地更新 (out-of-place update),即新的数据总是写入到新的位置。LSM-tree将数据组织成多个层级(Level),从内存中的C0(MemTable) 开始,数据会周期性地刷写到磁盘上的L1层,然后通过压缩 (compaction)操作将数据从较低层级合并到较高层级,从而保持数据排序并删除旧版本数据,减少写放大 (write amplification)。 -
元数据 (Metadata):关于数据的数据。在KV-SSD中,元数据主要指用于定位闪存 (flash)中键值对物理位置的信息,例如键及其对应的物理页面地址 (Physical Page Address, PPA)。元数据通常存储在SSD内部的动态随机存取存储器 (DRAM)中以加快访问速度。 -
尾延迟 (Tail Latency):衡量系统响应时间分布高端的性能指标,例如95th百分位延迟 (95th percentile latency)或99th百分位延迟 (99th percentile latency)。它表示95%或99%的请求在规定时间内完成。尾延迟对于许多交互式应用程序至关重要,因为它直接影响用户体验。 -
输入输出操作每秒 (IOPS):每秒可以完成的输入/输出操作(读取或写入)的数量。它是衡量存储设备性能的关键指标,反映了设备处理请求的能力。 -
写放大 (Write Amplification, WA):在固态硬盘 (SSD)中,由于闪存 (flash)的擦除 (erase)单元 (块 (block)) 大于写入 (write)单元 (页 (page)),以及LSM-tree等数据结构的压缩 (compaction)操作,实际写入闪存的数据量可能远大于主机 (host)发出的逻辑写入数据量。写放大会缩短SSD的设备寿命并降低性能。 -
垃圾回收 (Garbage Collection, GC):固态硬盘 (SSD)为了回收包含无效数据 (invalid data)的块 (block)而执行的内部操作。闪存 (flash)无法原地更新 (in-place update),当数据被修改或删除时,旧的数据会变成无效数据。GC会将有效数据 (valid data)从受害者块 (victim block)移动到新的块,然后擦除整个受害者块。 -
压缩 (Compaction):在LSM-tree中,压缩是将数据从一个或多个层级读取,合并排序,并写入到下一个层级的过程。它旨在维持LSM-tree的结构、删除重复或无效数据、并释放空间。
3.2. 前人工作
论文在 KV存储 (KV store) 的执行模型和 KV-SSD 的设计方面介绍了相关工作。
3.2.1. KV存储 的三种执行模型
KV存储 在目标系统中有三种不同的托管模型,取决于存储的使用方式:
-
主机 (Host)+块设备 (Block device): (如 Figure 3(a) 所示)- 描述: 这是最传统的模型,
KV存储软件(如RocksDB[22] 和LevelDB[27])运行在主机系统中,并通过标准的块输入输出 (block I/O)接口访问一个或多个传统块设备固态硬盘 (SSDs)。 - 优点: 不需要对系统进行任何修改,兼容性好。
- 缺点: 性能受限于复杂的
软件栈 (software stack),每次访问底层存储都需要经过操作系统内核 (OS kernel)和文件系统 (file system)等层级,导致延迟 (latency)高。 - 相关工作: 许多工作 [7, 11, 18-20, 44, 46-49, 61] 致力于通过优化
主机端的KV存储软件来提高性能。另一些工作 [12, 16, 23, 35, 37, 54, 56, 60] 引入了字节可寻址持久内存 (byte-addressable persistent memory)来减少块输入输出 (block I/O)流量。
- 描述: 这是最传统的模型,
-
主机+SSD支持: (如 Figure 3(b) 所示)- 描述: 为了解决传统模型中
软件栈笨重以及将SSD视为“黑盒”的问题,这种模型尝试利用SSD独特的特性或内部结构/行为来提升性能。 - 优点: 允许
主机软件更深入地与SSD交互,例如利用SSD内部的并行性或事务持久性 (transactional persistence)。 - 缺点: 仍然需要
主机端一定程度的软件参与,且对SSD接口有特定要求。 - 相关工作: 例如,有研究定义了新的
SSD接口以利用设备内部并行性 (device-internal parallelism)或闪存 (flash)命令的事务持久性[50]。另有工作针对开放通道 SSD (Open-Channel SSD)修改内核驱动 (kernel driver)以优化缓存 (caching)和调度 (scheduling)机制 [63]。
- 描述: 为了解决传统模型中
-
键值对固态硬盘 (KV-SSD): (如 Figure 3(c) 所示)-
描述: 最新的方法是将整个
KV存储引擎直接集成到SSD设备本身,由SSD自身管理KV存储。 -
优点: 相比前两种方法,它能提供更高的性能、更好的可伸缩性和更高效的设备管理 [4, 36, 38]。应用程序可以直接向
KV-SSD发出键值对 (KV pair)请求,无需经过复杂的软件栈。 -
缺点:
SSD内部资源(如CPU、DRAM)有限,需要精巧的设计来克服这些限制。 -
相关工作: 存在各种具有不同内部结构、行为和接口的
KV-SSD设计 [8, 13, 24, 30-32, 36, 43, 51, 64]。本文提出的AnyKey就属于这一类。下图(原文 Figure 3)对比了三种
KV存储执行模型,并展示了KV-SSD的内部架构:
该图像是一个柱状图,展示了不同工作负载下的页面写入总数。各个工作负载的页面写入数量(以百万计)通过三种不同的设计(Pink、AnyKey 和 AnyKey+)进行比较,显示出在转换条件下 AnyKey 的优势。
-
3.2.2. 现有 KV-SSD 设计
KV-SSD 的硬件架构与传统 块存储 SSD 相同(如 Figure 3(d) 所示),包括 闪存芯片 (flash chips)、块 (blocks)(擦除 (erase) 单元)和 页 (pages)(读/写 (read/write) 单元)。KV对 (KV pairs) 直接存储在 页 中,因此 KV-SSD 需要 元数据 (metadata) 来定位目标 KV对,这些 元数据 通常保存在 设备内部动态随机存取存储器 (device-internal DRAM) 中。管理 元数据 的数据结构主要有 哈希表 (hash tables) 和 日志结构合并树 (LSM-trees)。
-
基于
哈希表的KV-SSD:- 描述:
KV-SSD早期设计主要基于哈希表[8, 24, 32, 36, 64],因其简单性而受到青睐。 - 问题:
原地更新 (in-place update)机制:哈希表的原地更新会在写入时产生局部页更新 (partial page updates),频繁触发垃圾回收 (GC)操作,从而浪费带宽 (bandwidth)和设备寿命 (device lifetime)。哈希冲突 (hash collision): 为了将哈希表放入有限的DRAM,需要减小其大小,但这会增加哈希冲突的频率,导致读取 (read)操作时尾延迟 (tail latencies)增加。
- 局限性: 其他排序索引结构,如
B树 (B-trees)[15] 和学习索引 (learned indexes)[18, 40],也可能不适用,因为它们也需要原地更新,在写密集 (write-heavy)工作负载下会导致SSD的设备管理问题。
- 描述:
-
基于
LSM-tree的KV-SSD:- 描述:
LSM-tree因其闪存友好 (flash-friendly)的非原地更新 (out-of-place update)机制而日益流行。它通过多级索引结构来确保有界的尾延迟。 - 优势: 避免了
原地更新带来的GC问题,更适合SSD特性。 - 当前主流: 近期提出的
KV-SSD设计都基于LSM-tree[13, 30, 31, 43, 51],本文提出的AnyKey也采用了LSM-tree。
- 描述:
3.2.3. PinK 的结构和操作
论文选择 PinK [30, 31] 作为 最先进的 (state-of-the-art) LSM-tree-based KV-SSD 的代表进行重新评估和比较。尽管 PinK 是为通用 KV-SSD 设计的,但其核心设计理念与其他当代 LSM-tree-based KV-SSDs 相似。
KV-SSD 的内部结构与通用 LSM-tree-based KV store 有所不同。通用 LSM-tree 将 KV对 (KV pairs) 排序并维护在 排序字符串表 (Sorted String Tables, SSTables) 文件中。而 KV-SSD 中,文件物理上分散在 闪存 (flash) 中,需要新的数据结构来协同功能,类似 SSTables。
下图(原文 Figure 4)展示了 PinK 的内部结构以及如何定位目标 KV对:

PinK 的内部结构:
数据段 (Data segment): 实际的KV对存储在闪存中,并作为数据段进行管理。简单来说,每个闪存页 (flash page)可以是一个数据段,其中包含多个KV对。元段 (Meta segment): 一个元段可以适应一个闪存页,它维护着排序的键 (keys)以及指向相应KV对的物理闪存地址 (Physical Flash Address, PPA)。由于DRAM容量有限,PinK将LSM-tree上层(如L1,L2)的元段保存在设备内部动态随机存取存储器 (device-internal DRAM)中,而下层(如L3到Ln)的元段则存储在闪存页 (flash pages)中。层级列表 (Level list): 每个元段都有一个对应的层级列表条目,其中包含该元段的第一个(或最小的)键以及元段的位置(DRAM地址或闪存地址)。这些层级列表条目被分组到多个层级 到 ,每个层级列表内的条目都是排序的。
PinK 的操作流程:
-
定位
KV对(读取 (read)操作): 如 Figure 4 所示,以键“PP”为例。- 给定
键,首先从 开始,依次搜索层级列表。如果当前层级列表中未找到,则检查下一个层级列表。 - 一旦找到
“PP”可能落入的层级列表条目,其对应的元段会被读取到DRAM地址0x10。 - 然而,
“PP”可能不存在于该元段中,因为层级列表的键范围可能跨不同层级重叠。在这种情况下,会搜索下一个层级。 - 如果在 中找到另一个
层级列表条目,并且其对应的DRAM地址0x20中的元段确实包含“PP”,则可以获取目标KV对所在数据段的位置。 - 最后,从
闪存地址 901读取数据段,并提取目标值。
- 给定
-
更新现有
键或添加新键(写入 (write)操作):写入请求 (write request)首先缓冲在设备内部动态随机存取存储器 (device-internal DRAM)中。- 当
缓冲区 (buffer)满时,其中的KV对会被合并到 中(即L0-L1压缩)。 - 这个创建新 的过程包括为相应
键在DRAM中生成新的层级列表条目和元段,同时值被写入到闪存中的数据段。简而言之,每个写入请求首先从缓冲区立即响应,然后成为LSM-tree的一部分。
3.3. 技术演进与差异化分析
3.3.1. 技术演进
KV存储 技术从最初在 主机 (host) 系统上运行并使用传统 块设备 (block-based) 固态硬盘 (SSDs) 发展而来。这种传统方式通过标准 I/O 栈 (I/O stack) 导致性能瓶颈。为了解决此问题,研究者们尝试利用 SSD 内部特性或提供新的 SSD 接口来优化 KV存储,但 主机 端仍需承担部分管理职责。
最终,KV-SSD 概念应运而生,将 KV存储 功能直接移入 SSD 设备内部,实现了 KV存储 与底层 闪存 (flash) 的深度融合。在 KV-SSD 内部数据结构的选择上,经历了从早期基于 哈希表 (hash tables) 的简单设计到如今主流的基于 日志结构合并树 (LSM-trees) 的演进。LSM-trees 因其 非原地更新 (out-of-place update) 特性,天然地对 闪存 友好,能有效减少 写放大 (write amplification),并提供可控的 尾延迟 (tail latencies)。PinK 就是 LSM-tree 在 KV-SSD 领域的一个 最先进 (state-of-the-art) 实现。
3.3.2. 差异化分析
AnyKey 与 PinK 等现有 LSM-tree-based KV-SSD 设计的核心区别在于它们对 元数据 (metadata) 的处理方式以及对不同工作负载的适应性:
-
元数据粒度和存储位置:PinK(及现有设计):元数据(主要是元段 (meta segments))中包含每个键值对 (KV pair)的完整键 (key)信息,以及指向其在闪存 (flash)中数据段 (data segment)的指针。在高值键比 (high-v/k)工作负载(键小)下,这些元数据可以完全驻留在设备内部动态随机存取存储器 (device-internal DRAM)中。然而,在低值键比 (low-v/k)工作负载(键相对大)下,元数据的总大小会急剧膨胀,超出DRAM容量,导致部分元段被迫存储在闪存中。这使得读取 (read)请求需要额外的闪存访问来获取元数据,从而显著增加尾延迟。AnyKey: 采取“以组为单位”的元数据管理策略。它将多个KV对排序并组织成数据段组 (data segment group)。DRAM中的层级列表 (level list)条目只存储每个数据段组的最小键、数据段组的起始物理页面地址 (PPA)以及每个页面内第一个键的哈希值 (hash values)列表。通过这种方式,AnyKey显著减少了元数据的总体大小,确保其能够完全驻留在DRAM中,即使在low-v/k工作负载下也是如此。此外,AnyKey还引入了哈希列表 (hash lists)来在闪存访问前进行快速存在性检查,进一步减少不必要的闪存读取。
-
值 (value)的管理:PinK:KV对的键和值通常存储在一起,或者元数据直接指向包含键和值的数据段。在LSM-tree压缩 (compaction)过程中,如果KV对需要移动,则整个值也必须被读取和重写,尤其是在值很大的情况下,会消耗大量带宽 (bandwidth)和设备寿命。AnyKey: 为了提高LSM-tree管理效率,AnyKey引入了值日志 (value log)。它将值与键分离存储。新的KV对的值首先写入值日志。数据段组中的KV实体 (KV entity)可能只存储指向值日志中值位置的指针,而不是值本身。这使得压缩过程主要处理键和元数据的移动,而大部分值可以原地不动,显著减少了闪存写入量。
-
压缩链 (compaction chain)的处理:-
AnyKey(基础版): 尽管AnyKey优化了元数据和值的管理,但在某些高值键比或值相对较大的low-v/k工作负载下,日志触发压缩 (log-triggered compaction)仍可能导致大量值被合并到数据段组中,从而触发目标层级 (destination level)达到阈值,进而引发连续的树触发压缩 (tree-triggered compaction),形成压缩链,影响性能。 -
(增强版): 通过修改
日志触发压缩机制来解决压缩链问题。它在压缩过程中监控目标层级的大小。一旦目标层级达到某个阈值,剩余的值将被写回值日志,而不是强制合并到数据段组中,从而避免压缩链的产生。此外, 在选择日志触发压缩的源层级 (source level)时,会优先选择包含最多无效值 (invalid values)的层级,进一步提高值日志的空间回收效率。通过这些关键差异,
AnyKey能够有效解决现有KV-SSD在low-v/k工作负载下的性能瓶颈,而 则通过优化LSM-tree的管理效率,使其成为一个在所有KV工作负载类型下都表现优异的通用KV-SSD解决方案。
-
4. 方法论
4.1. 方法原理
AnyKey 的核心方法原理是:针对现有 KV-SSD 设计在 低值键比 (low-v/k) 工作负载下 元数据 (metadata) 大小急剧膨胀,导致 尾延迟 (tail latency) 增加和 输入输出操作每秒 (IOPS) 下降的问题,通过最小化 元数据 的粒度,并将 值 (value) 从 键 (key) 中分离,从而确保 元数据 能够完全驻留在 设备内部动态随机存取存储器 (device-internal DRAM) 中,并优化 日志结构合并树 (LSM-tree) 的管理效率,最终实现对所有工作负载类型的通用高性能支持。
其直觉是,如果 键 很大,那么为每个 键值对 (KV pair) 存储完整 键 的 元数据 会很快耗尽 DRAM。但如果将 KV对 分组,并只为每个组存储少量 元数据(例如,组的起始 键 和一些 哈希值 (hash values)),就可以显著减少 DRAM 的需求。同时,将 值 分离到单独的 值日志 (value log) 中,可以避免在 LSM-tree 压缩 (compaction) 过程中频繁移动大 值,从而节省 闪存 (flash) 带宽和延长 设备寿命 (device lifetime)。
4.2. 核心方法详解
4.2.1. 重新评估当前设计 (PinK) 的结构性限制
本文首先重新评估了 最先进的 (state-of-the-art) LSM-tree-based KV-SSD 设计 PinK [30],特别是在 低值键比 (low-v/k) 工作负载下的行为,从而揭示了其结构性限制。
PinK 的内部结构如 Figure 4 所示,它将实际的 KV对 存储在 数据段 (data segments) 中,而它们的 键 (keys) 和指向 KV对 的指针则排序后存储在 元段 (meta segments) 和 层级列表 (level lists) 中。这些 元数据 结构主要保存在 设备内部动态随机存取存储器 (device-internal DRAM) 中。
作者通过假设一个 64GB SSD 包含 64MB DRAM 并已填满 KV对 的情况,分析了 PinK 在不同工作负载下的行为。下图(原文 Figure 5)展示了 PinK 在 高值键比 (high-v/k) 和 低值键比 (low-v/k) 工作负载下的对比行为:
该图像是图表,展示了在不同 DRAM 大小下的读延迟的累积分布函数(CDF)。图中包含三种不同负载的比较,分别是 Crypto1、ETC 和 W-Pink,横轴为延迟(ms),纵轴为 CDF。各负载使用不同的 DRAM 大小(32MB、64MB、96MB)进行标识,提供了延迟性能的直观对比。
从 Figure 5 中可以观察到两种截然不同的行为:
-
在
高值键比 (high-v/k)工作负载下 (Figure 5a): 由于键的大小很小,层级列表和元段(包含键)的总体大小非常小,大部分可以驻留在DRAM中。因此,定位键大部分可以在DRAM内部完成,每个请求的闪存访问 (flash accesses)次数被限制在最多 3 次 (Figure 5b)。 -
在
低值键比 (low-v/k)工作负载下 (Figure 5a): 随着值键比 (value-to-key ratio)的降低(即键的相对大小增加),层级列表和元段的累计大小显著增加。由于DRAM容量固定,它们无法完全容纳在DRAM中,部分元数据必须存储在闪存中。-
对于
值键比相对较高的low-v/k工作负载(例如UDB,ETC,Xbox),只有元段被存储在闪存中。这可能导致每次读取 (read)请求需要额外的一两次闪存访问来获取这些元段以定位KV对。 -
对于
值键比相对较低的low-v/k工作负载(例如Crypto1,ZippyDB,Cache15),除了整个元段外,一些层级列表也被存储在闪存中。在这种情况下,搜索请求的键将涉及多次额外的闪存读取来获取闪存中的层级列表,这会严重损害整体性能。这些观察表明,现有
LSM-tree-based KV-SSD设计在low-v/k工作负载下的性能瓶颈在于元数据大小随着键的相对增大而迅速膨胀,超出了DRAM容量,导致频繁的闪存访问。
-
4.2.2. AnyKey 设计原则与整体结构
为了解决上述问题,AnyKey 提出了以下设计原则和相应的结构。下图(原文 Figure 6)展示了 AnyKey 的内部结构:
该图像是图表,显示了在不同工作负载下,Crypto1、ETC 和 W-Pink 三种情形下的读取延迟的累积分布函数(CDF)。图中包含了4KB、8KB和16KB三种页面大小的延迟比较,横坐标为延迟(毫秒),纵坐标为CDF值。不同颜色和线型表示不同的页面大小。
4.2.2.1. 最小化 元数据 大小
为了减少 元数据 (metadata) 的大小,AnyKey 建议以组的形式管理 KV对 (KV pairs),其中 KV对 自身是排序的。传统的 KV-SSD 设计要求每个 KV对 都有自己的 元数据 来直接定位它。而 AnyKey 的方法是,如果许多 KV对 被排序并作为一个组进行管理,那么组内的目标 KV对 就可以仅使用组的 元数据 来定位。
-
数据段组 (Data segment group)(在闪存中):- 概念:
AnyKey将多个闪存页 (flash pages)组合成一个数据段组,其中存储的多个KV对是排序的。这样做可以显著减少元数据的总大小,因为它只需要为每个数据段组而非每个KV对维护元数据。 - 定位机制: 由于每个组内的
KV对是排序的,因此仍然可以使用组的元数据来定位目标KV对。AnyKey当前的实现中,将一个闪存块 (flash block)内相邻的物理页组合成一个数据段组。由于一个块内的物理页面地址 (PPAs)是连续的,因此只需知道组中第一个页面的PPA就可以访问数据段组内的任何闪存页。 - 组内
KV对定位: 一旦确定了目标数据段组,高效定位存储目标KV对的闪存页至关重要,否则可能需要读取数据段组中的所有闪存页。- 挑战: 如果简单地在组
元数据中保留每个闪存页的第一个键 (key),当键较大时(即在low-v/k工作负载下),元数据大小会再次显著增加。 - 解决方案:
哈希值 (hash values)排序:AnyKey引入了小尺寸哈希值 (small-sized hash values)来表示大尺寸键,并使用这些哈希值对数据段组内的KV对进行排序。 KV实体 (KV entity)结构: 每个数据段组中的KV对以{(i) 键, (ii) 键的哈希值, (iii) 值}的形式存储,称之为KV实体。- 对于
(ii) 哈希值:分析表明,使用32位哈希值 (32-bit hash values)足以在包含数千个KV对的数据段组中唯一标识键。与基于哈希的KV-SSD不同,AnyKey中需要维护在DRAM中的哈希值数量非常少。 - 对于
(iii) 值:KV实体中可以直接存储值,或者,如果值存储在单独的值日志 (value log)中,则存储一个指向值所在值日志位置的PPA。
- 对于
哈希冲突位 (Hash collision bits): 如果数据段组中不同的键偶然具有相同的哈希值,这些KV实体将连续存储。为了处理这种情况,AnyKey为每个闪存页预留2位,称为哈希冲突位。如果需要读取下一页才能找到具有相同哈希值的KV实体,则设置为01;如果需要读取上一页,则设置为10。论文分析指出,这种情况发生率仅为0.075%,对整体性能影响可忽略。
- 挑战: 如果简单地在组
- 当前实现细节: 当前实现将
32个 8KB 闪存页组合成一个数据段组,可容纳100-5,000个 KV对。数据段组的大小选择平衡了元数据减少量和潜在的哈希冲突带来的额外读取。
- 概念:
-
层级列表 (Level lists)(在DRAM中):- 概念:
AnyKey也使用层级列表来容纳组元数据。每个层级列表条目被重新设计以包含对应数据段组的元数据。 层级列表条目结构 (在DRAM中):{(i) 最小键, (ii) 第一页的PPA, (iii) 页面中第一个键的哈希值列表}。(i) 最小键 (smallest key):用于在层级列表中识别目标数据段组,因为层级列表条目在每个层级都是排序的。(ii) 第一页的PPA (PPA of the first page):一旦目标数据段组被识别,可以使用此PPA访问组内的所有闪存页。(iii) 页面中第一个键的哈希值列表 (list of the hash values of the first keys in the pages):由于数据段组中的所有KV对都根据键的哈希值进行排序,通过在哈希值列表中搜索目标键的哈希值,可以轻松找到目标闪存页。
- 当前实现细节: 为了进一步减少
层级列表条目的大小,当前实现只使用哈希值的前16位(Hash[0:15])。
- 概念:
4.2.2.2. 进一步减少 闪存访问
上述 数据段组 和 层级列表 的组合可能仍需额外的 闪存访问。原因在于:(i) 层级列表 仅提供 键 的范围;(ii) 键 的范围可能跨不同层级重叠,即使 键 落入某个 层级列表 条目,对应的 数据段组 也可能不包含目标 KV对。这个问题也存在于其他 LSM-tree-based 设计中。AnyKey 引入了一个机制来检查目标 KV对 是否确实存在于一个 数据段组 中。
哈希列表 (Hash lists)(在DRAM中):- 概念:
AnyKey在LSM-tree中引入了一种新的元数据类型,称为哈希列表。每个层级列表条目都有一个哈希列表,其中维护了实际存在于对应数据段组中的所有键的哈希值。 - 作用: 如果目标
键的哈希值未在哈希列表中找到,则表明目标KV对不存在于该数据段组中,从而继续在下一个层级列表中搜索,避免了不必要的闪存读取。 - 存储与优先级:
哈希列表利用剩余的DRAM空间来存储。如果DRAM空间不足,则不对较低层级的层级列表维护哈希列表。在这种情况下,AnyKey也无法避免额外的闪存访问。然而,由于AnyKey将大量KV对分组,显著减少了层级列表元数据的大小,因此在可用DRAM空间中引入哈希列表可以进一步提升性能。 - 实现细节: 当前实现使用整数数组作为
哈希列表,并采用二分查找 (binary search)来搜索哈希值。论文指出,使用Bloom Filter或Cuckoo Filter虽然可以节省DRAM空间,但生成这些过滤器 (filters)需要密集的计算,对SSD内部资源造成显著负担,因此PinK[31] 也未采用此类过滤器。
- 概念:
4.2.2.3. 提高 LSM-tree 管理效率
上述 AnyKey 设计虽然可以改善 读取延迟 (read latency),但也可能增加 LSM-tree 管理的开销。具体来说,由于 层级列表 直接指示存储 键 和 值 的 数据段组,在 压缩 (compaction) 过程中,如果 KV对 需要移动,则目标 数据段组 中所有 KV对 的 值 都将被读取和写入,从而大量浪费 设备带宽 (device bandwidth) 和 设备寿命 (device lifetime)。
值日志 (Value log)(在闪存中):- 概念: 为了防止在
压缩过程中移动数据段组中的所有值,AnyKey将值从数据段组中分离出来,并单独管理。为此,AnyKey引入了一个新的数据结构,称为值日志,它位于闪存的一个单独区域中,专门用于存储值。 - 存储策略:
AnyKey中的闪存空间被划分为两个区域:一个用于数据段组,另一个用于值日志。每个KV对的值可以存储在这两个区域之一:要么直接在数据段组的KV实体 (KV entity)中,要么在值日志中。在后一种情况下,KV实体将包含一个指向值日志中值存储位置的指针。 - 写入流程: 最初,所有
写入 (writes)操作的值都被写入值日志。随后,其中一些值会被合并到数据段组中,以确保值日志有可用空间继续服务新的写入。 值迁移:值从值日志移动到数据段组的过程在压缩过程中执行(详见4.2.3.2 压缩部分)。值日志大小:AnyKey将SSD剩余容量的一半用于值日志区域。这是因为LSM-tree会随着新的KV对加入而增长。即使值日志中所有值都属于新KV对,AnyKey仍然可以利用另一半剩余容量将它们合并到数据段组中。如果SSD容量已满,AnyKey可以利用预留空间 (over-provisioned, OP)容量的一半作为值日志。论文分析指出,即使是小的值日志仍然有益,因为OP通常用于容纳更新的值。
- 概念: 为了防止在
4.2.3. 详细操作
4.2.3.1. 读取 (Read) 操作
给定一个 键 (key) 请求,AnyKey 使用 层级列表 (level lists) 和 哈希列表 (hash lists) 来查找目标 数据段组 (data segment group),进而找到其中的 KV实体 (KV entity) 和目标 值 (value)。如果 KV实体 存储的是目标 值 的位置信息,AnyKey 则从 值日志 (value log) 中读取 值。
以下是 Figure 6 中读取 键 “PP”(其 哈希值 为 “4791”)的示例:
AnyKey从 到 依次搜索层级列表。- 如果在某个
层级列表中检测到一个条目 (entry),键 “PP”落入其键范围,AnyKey会检查“PP”的哈希值(“4791”) 是否存在于对应的哈希列表中。 - 如果
哈希值未找到,则表明目标KV实体不存在于该层级列表条目所指示的数据段组中,AnyKey会继续在下一个层级搜索。 - 如果另一个
层级列表条目被选为候选,并且其哈希值也在对应的哈希列表中找到,那么目标数据段组就被识别。 - 在组内的
闪存页 (flash pages)中,PPA 300中的第一页被选中并读取,因为哈希值的前16位(“47”) 介于层级列表条目中前两个16位哈希值(“12”和“66”) 之间。 - 如果目标
KV实体直接包含值,则读取完成。 - 否则,从
KV实体中提取值的实际位置,并从值日志中读取该页面(PPA 901)。
4.2.3.2. 写入 (Write) 操作
与大多数 KV-SSD 设计 [13, 30, 31, 43, 51] 类似,写入请求 (write request)(对现有 键 的更新或新添加的 键)首先缓冲在 设备内部动态随机存取存储器 (device-internal DRAM) 中。当 缓冲区 (buffer) 满时,其中的 KV对 (KV pairs) 会合并到 L1 层(即 L0-L1 压缩 (compaction))。具体来说,新的 数据段组 (data segment groups) 和 L1 的 层级列表 (level list) 条目被构建(所有 值 (values) 被写入 值日志 (value log))。简单来说,加入 LSM-tree 的新 值 都写入 值日志。
4.2.3.3. 压缩 (Compaction) 操作
与传统的 LSM-tree-based KV-SSD 采用的 压缩 过程相似,AnyKey 中的 到 压缩 也包括:(i) 读取来自两个层级的所有 KV对,(ii) 根据 键 对它们进行排序,以及 (iii) 顺序地构建新的 数据段组 和 的对应 层级列表 条目。然而,AnyKey 的 压缩 过程具有两个显著特点:
-
在 (i) 阶段(即读取目标层级的
KV对时),每个KV对的值都从其当前存储位置读取,这可以是数据段组或值日志。 -
在 (iii) 阶段(即创建每个
数据段组并写入闪存 (flash)时),KV实体 (KV entities)会根据键的哈希值 (hash values)再次排序。压缩操作在以下两种情况下触发:(i) 当一个层级的大小超过其阈值时(称为树触发压缩 (tree-triggered compaction)),以及 (ii) 当值日志变满时(称为日志触发压缩 (log-triggered compaction))。下图(原文 Figure 8)展示了AnyKey中采用的压缩操作:
该图像是图表,展示了在不同 heta值下,AnyKey、AnyKey+ 和 PinK 的延迟分布曲线(CDF)。从图中可以看出,随着heta值的变化,AnyKey 的延迟表现优于其他方案。
-
树触发压缩 (Tree-triggered compaction):- 当
LSM-tree的 层(即其数据段组和值日志中引用的值的总大小)达到其阈值时,会触发一个 到 的压缩。这是维护LSM-tree非原地更新 (out-of-place update)机制所需的常规压缩操作。
- 当
-
日志触发压缩 (Log-triggered compaction):AnyKey还会为确保值日志中的可用空间而触发压缩。当值日志变满时,会选择一个目标(源)层级 ,并触发一个 到 的压缩。- 在
压缩过程中, 和 中值日志内的所有值都将被重新定位到新创建的 的数据段组中,从而在值日志中创建可用空间。 - 对于目标层级 ,
AnyKey会选择值日志中其值大小最大的层级,因为这样做在回收值日志的空闲空间方面最有利。
-
哈希列表更新: 值得注意的是,当两种类型的压缩操作都被触发且层级列表被修改时,AnyKey会检查可用的DRAM空间并相应地更新顶层哈希列表。由于压缩操作涉及大量的闪存读取和写入,在DRAM中更新哈希列表只会产生很小的开销,并且可以有效地隐藏。
4.2.3.4. 垃圾回收 (GC) 操作
传统 垃圾回收 (GC) 操作会重新定位 受害者块 (victim block) 中所有 有效数据 (valid data)(以 页 (page) 为单位),然后擦除该 块。而在 AnyKey 中,GC 操作的特点是:(i) 它重新定位 受害者块 中每个 数据段组(以多个 页 为单位),并且在 组 重新定位后,(ii) 其新的 物理页面地址 (PPA) 会在对应的 层级列表 (level list) 条目中更新。
根据观察,AnyKey 中的大多数 受害者块 不包含任何 有效数据,因此 GC 操作可以直接擦除它们,无需耗时的 有效数据 重新定位过程,从而使得整体 GC 开销非常低。这是因为一个层级的 数据段组 往往存储在同一个 块 中,并且这些 块 中的 组 在 压缩 (compaction) 操作(两种类型)期间会一起重新定位。此外,值日志 (value log) 中不会触发 GC 操作,因为 值日志 中 闪存块 的回收在 日志触发压缩 (log-triggered compaction) 期间执行。
4.2.3.5. 范围查询 (Range query) 操作
由于 KV对 (KV pairs) 在每个 数据段组 (data segment group) 内部是根据其 哈希值 (hash values) 排序的,因此对于 范围查询,如果需要根据 键 (keys) 重新排序,将需要大量的计算。为了解决这个问题,AnyKey 维护额外的定位信息 {目标页 (target page), 页偏移量 (page offset)} 来定位 数据段组 中的每个 KV对。这些信息根据 键 进行排序,并存储在 数据段组 的第一个页面中。利用这些信息,范围查询 请求的 KV对 可以快速定位,无需任何排序过程。
值得强调的是,随着 范围查询 长度的增加,AnyKey 的 范围查询 性能会提高。这是因为 范围查询 的性能取决于需要读取的 闪存页 (flash pages) 数量,而 AnyKey 对于较长的 范围查询 需要读取的页数更少。具体来说,范围查询 请求的 KV对 存储在 数据段组 的 闪存页 中是聚簇的,因此读取它们只需访问少数 闪存页。相比之下,在 PinK 中,尽管 键 和指向其 值 (values) 的指针在 元段 (meta segments) 中是排序的,但 数据段 中的相应 KV对 却分散在不同的 闪存页 中。因此,PinK 中的 范围查询 需要读取大量的 闪存页。对于小型 范围查询,AnyKey 也能表现出与 PinK 相当的性能,因为它可以直接使用存储在第一个页面中的位置信息来定位目标 KV对,而无需对 KV对 进行排序。
4.2.4. 元数据 大小分析
本文对 元数据 (metadata) 的大小进行了定量分析,以了解 AnyKey 相对于 PinK 能减少多少。下表(原文 Table 1)比较了 PinK 和 AnyKey 在不同 值键比 (value-to-key ratios) 下的 元数据 数据结构大小,假设 64GB SSD 已填满 KV对:
| Workload | PinK | AnyKey | ||||
| Level lists | Meta segments | Sum | Level lists | Hash lists | Sum | |
| 4.0 (160B/40B) | 56MB | 316MB | 372MB | 29MB | 35MB | 64MB |
| 2.0 (120B/60B) | 117MB | 414MB | 531MB | 34MB | 30MB | 64MB |
| 1.0 (80B/80B) | 200MB | 503MB | 703MB | 38MB | 26MB | 64MB |
观察结果:
- 当
值键比相对较低时,AnyKey中元数据的总大小远小于PinK。 - 这是因为
AnyKey中层级列表的大小显著减小,并且其哈希列表仅使用剩余的DRAM空间生成,将两个数据结构的总大小限制在DRAM容量内。 - 因此,即使
值键比极度下降,AnyKey也能阻止元数据总大小的增加。AnyKey减少元数据大小的关键机制是为多个KV对组成的组(即数据段组)生成元数据。
4.2.5. 设计开销
4.2.5.1. 存储容量开销 (Storage Capacity Overhead)
在 AnyKey 中,数据段组 (data segment group) 中的每个 KV实体 (KV entity) 包含其 键 (key) 的 32位哈希值 (32-bit hash value)。如果一个 64GB SSD 中有 一千万 (ten million) KV对 (KV pairs),那么这些 32位哈希值 的总大小为 38MB,仅占整个 SSD 容量的 0.05%。此外,每个 数据段组 需要维护组内所有 KV对 的位置信息(即 {目标页 (target page), 页偏移量 (page offset)})以实现快速 范围查询 (range query) 处理。假设一个包含 32个 8KB 页 的组中有 1,000个 KV对,这些信息的总大小为 2KB,不到整个 组 大小的 1%。
这种集体开销相对于 PinK 来说极小。在 PinK 中,如果 元段 (meta segments) 无法容纳在 DRAM 中,它可能需要在 闪存 (flash) 中存储每个 键 的两个不同副本(一个来自 元段,另一个来自 数据段),从而导致更高的存储开销。
4.2.5.2. 计算开销 (Computation Overhead)
在 KV-SSD 设计中采用 哈希值 (hash values) 会引入相关的计算任务:
-
哈希值生成: 当KV对首次写入日志结构合并树 (LSM-tree)时,以及在给定读取请求 (read request)时,AnyKey需要为键生成32位哈希值。在当前实现中,采用了xxHash[14] 算法。在1.2 GHz ARM Cortex-A53核心(现代SSD中常用的计算资源 [5])上,从一个40字节键生成32位哈希值需要79纳秒 (79ns)。与典型的闪存读取或写入延迟相比,这是一个边际开销。 -
KV实体排序: 在压缩 (compaction)过程中构建数据段组时,AnyKey需要根据键的哈希值对一组KV实体进行排序。由于每个要合并的组已经包含排序的KV实体,因此排序时间非常短。合并两个包含8,192个排序KV实体的数据段组,在ARM Cortex-A53核心上大约需要118微秒 (118us)。与耗时的压缩操作相比,这个开销可以忽略不计。论文强调,第 5 节中提供的所有实验数据都已包含了上述计算开销。
4.2.6. 压缩 过程的增强 ()
4.2.6.1. 动机观察 (Motivational Observations)
作者观察到,虽然 AnyKey 在 低值键比 (low-v/k) 工作负载下 输入输出操作每秒 (IOPS) 显著提高,但在 高值键比 (high-v/k) 工作负载下,以及在 low-v/k 工作负载中 值 (values) 相对较大的情况下,IOPS 会下降。分析表明,在这些工作负载中,在 日志触发压缩 (log-triggered compaction) 期间,大量的 值 被合并到 数据段组 (data segment groups) 中。这反过来导致目标(目的地)层级达到其阈值,并连续触发 树触发压缩 (tree-triggered compaction)。作者将这种连续的 压缩 调用称为 压缩链 (compaction chain)。下图(原文 Figure 9a)描述了发生 压缩链 的情况:
该图像是图表,展示了不同扫描长度下UDB的延迟CDF曲线,包括长度为100、150和200的三个子图。可以看出,AnyKey设计在多种工作负载下的延迟表现优于其他设计。
- 当
值日志 (value log)的大小达到其阈值时,会触发一个日志触发 (L_{n-1} – to – L_n)压缩( 被选为目标源层级,因为其值的总大小最大),因此大量值被合并到目的地层级 。 - 在
压缩过程中,目的地层级 达到其阈值,并连续触发一个树触发 (L_n – to – L_{n+1})压缩。
4.2.6.2. 修改后的 日志触发压缩 (Modified Log-Triggered Compaction)
为了避免 压缩链,AnyKey 添加了一个简单而有效的增强功能,其中 日志触发压缩 操作略作修改。具体来说,如 Figure 9b 所示,在 日志触发 (L_{n-1} – to – L_n) 压缩 期间:
-
AnyKey监控目标目的地层级 () 的大小是否达到其阈值(同时将值日志中的值合并到数据段组中)。 -
一旦目标目的地层级的大小达到某个点(即
阈值 × α,; 可以根据目标工作负载的键/值大小而变化),剩余的(要合并到数据段组的)值将被写回值日志。这样做可以防止压缩链的产生。然而,这可能会降低
日志触发压缩的效益(即值日志中回收的干净空间可能会减少),因为值在某个点后会被写回值日志。为此,AnyKey也改变了选择目标层级的方式。不再选择值日志中其值大小最大的层级,而是选择值日志中拥有最多“无效”值的层级。在LSM-tree中,由于其非原地更新 (out-of-place update)机制,通常一个键存在多个不同版本的值,显然值日志也包含大量的无效值。通过选择这样的目标层级,可以在避免压缩链的同时,进一步确保值日志中的可用空间。
5. 实验设置
5.1. 数据集
实验使用了 14 种 键值对 (KV) 工作负载,这些工作负载来自不同领域,具有不同的 键 (key) 和 值 (value) 大小,从而代表了 高值键比 (high value-to-key ratio, high-v/k) 和 低值键比 (low value-to-key ratio, low-v/k) 两种类型。
下表(原文 Table 2)列出了所有测试的 KV 工作负载(大小以字节为单位):
| Workload | Description | Key | Value |
|---|---|---|---|
| KVSSD[36] | The workload used in Samsung. | 16 | 4,096 |
| YCSB[17] | The default key and value sizes of YCSB. | 20 | 1,000 |
| W-PinK[31] | The workload used in PinK. | 32 | 1,024 |
| Xbox[19] | Xbox LIVE Primetime online game. | 94 | 1,200 |
| ETC[6] | General-purpose KV store of Facebook. | 41 | 358 |
| UDB[10] | Facebook storage layer for social graph. | 27 | 127 |
| Cache[58] | Twitter's cache cluster. | 42 | 188 |
| VAR[6] | Server-side browser info. of Facebook. | 35 | 115 |
| Crypto2[55] | Trezor's KV store for Bitcoin wallet. | 37 | 110 |
| Dedup[21] | DB of Microsoft's storage dedup. engine. | 20 | 44 |
| Cache15[59] | 15% of the 153 cache clusters at Twitter. | 38 | 38 |
| ZippyDB[10] | Object metadata of Facebook store. | 48 | 43 |
| Crypto1[9] | BlockStream's store for Bitcoin explorer. | 76 | 50 |
| RTDATA[26] | IBM's real-time data analytics workloads. | 24 | 10 |
数据集选择原因:
这些数据集的选择旨在覆盖广泛的实际应用场景,特别是为了揭示 低值键比 (low-v/k) 工作负载的挑战,这些工作负载在现有研究中未被充分探索。它们涵盖了从传统的大 值 小 键 (high-v/k)(如 KVSSD、YCSB、W-PinK)到大 键 小 值 (low-v/k)(如 Crypto1、RTDATA、ZippyDB)的不同 值键比 类型。通过这些多样化的工作负载,可以全面评估 AnyKey 设计的普适性和有效性。
5.2. 评估指标
论文使用了以下评估指标来衡量 KV-SSD 设计的性能和效率:
-
95th百分位尾延迟 (95th percentile tail latency):- 概念定义: 衡量请求响应时间的稳定性。它表示
95%的请求其响应时间都低于这个特定的值。这个指标对于衡量用户体验和系统在重负载下的表现至关重要,因为它可以反映少数极端慢速请求对整体用户感知的影响。 - 数学公式:
- 符号解释:
- :95th百分位尾延迟。
- :所有请求响应时间的集合。
- :一个函数,返回集合 中第 个百分位的值。
- 概念定义: 衡量请求响应时间的稳定性。它表示
-
输入输出操作每秒 (IOPS):- 概念定义: 衡量存储设备每秒能够处理的输入(读取)和输出(写入)操作的数量。
IOPS是评估存储系统吞吐量 (throughput)的一个核心指标,反映了设备处理并发请求的能力。 - 数学公式:
- 符号解释:
- :每秒输入输出操作数。
- :在测试期间完成的读取和写入操作的总和。
- :进行这些操作所花费的总时间(以秒为单位)。
- 概念定义: 衡量存储设备每秒能够处理的输入(读取)和输出(写入)操作的数量。
-
存储利用率 (Storage Utilization):- 概念定义: 衡量存储设备中有效、独特的数据所占的比例,相对于其总容量。这个指标反映了存储效率,高利用率意味着更少的冗余或未使用的空间。
- 数学公式:
- 符号解释:
- :存储利用率。
- :存储在设备中所有唯一的
键值对的总数据量。 - :
固态硬盘 (SSD)的总物理存储容量。
-
页面写入总数 (Total Number of Page Writes):- 概念定义: 记录
固态硬盘 (SSD)在操作过程中实际写入闪存 (flash)的页面总数。这个指标与写放大 (write amplification)直接相关,并影响SSD的设备寿命 (device lifetime)。较低的页面写入总数意味着更长的SSD寿命。 - 数学公式:
- 符号解释:
- :在整个执行阶段产生的页面写入总数。
- :所有写入操作的计数。
- :第 次写入操作写入的页面数。
- 概念定义: 记录
5.3. 对比基线
论文将 AnyKey 的两个版本(基础版 AnyKey 和增强版 )与 PinK [30, 31] 进行了比较。
PinK: 被认为是最先进的 (state-of-the-art)基于日志结构合并树 (LSM-tree)的键值对固态硬盘 (KV-SSD)设计。它在高值键比 (high value-to-key ratio)工作负载下表现良好,但在低值键比 (low value-to-key ratio)工作负载下存在性能瓶颈。
5.4. 实验环境与配置
-
测试平台 (Testbed):
- 基于广泛使用的
闪存模拟器 (flash emulator)FEMU[45] 构建。 - 利用
uNVMe驱动 [2] 的FIO 插件引擎 (FIO plugin engine)在用户空间生成目标工作负载请求,并使其直接发送到模拟SSD,绕过传统的软件栈 (software stack)。 - 将
PinK[31] 的公开源代码移植到此测试平台,并修改其数据结构以实现AnyKey。 - 源代码可访问性: 实现的源代码可在 https://github.com/chanyoung/kvemu 获得。
- 基于广泛使用的
-
设备配置 (Device configuration):
固态硬盘 (SSD)容量: 模拟一个64GB SSD。- 通道和芯片: 包含
8个通道 (channels),每个通道包含8个闪存芯片 (flash chips),与PinK[31] 的配置相同。 - 页面大小 (Page size): 默认为
8KB。 动态随机存取存储器 (DRAM)容量: 默认为64MB(通常设置为SSD总容量的0.1%[25, 39])。闪存 (flash)类型和时序: 假设为现代TLC 闪存 (TLC flash),读取 (read)、写入 (write)和擦除 (erase)时间分别设置为 、 和3ms,如 [34] 中所述。- 可伸缩性研究: 尽管主要模拟小型
SSD,但论文也指出AnyKey适用于大型SSD,并在第 5.9 节评估了4TB SSD与4GB DRAM的场景。
-
工作负载配置 (Workload configuration):
- 写入比例 (Write ratios): 所有工作负载的
写入比例均设置为20%。 键 (key)分布 (Key distribution): 默认使用Zipfian 分布 (Zipfian distribution), 值为0.99,表示键访问模式是偏斜的。也进行了不同 值的敏感性分析。输入输出 (I/O)队列深度 (I/O queue depth): 设置为64,理论上允许所有64个底层闪存芯片同时处理I/O请求。KV应用程序: 由于没有公开可用的KV应用程序用于评估KV-SSD设计(它们通过传统I/O 栈生成块 I/O追踪),KV-SSD研究通常依赖于KV生成器(例如基于FIO 引擎),通过调整键/值大小、读/写比例和访问分布等属性来生成工作负载。
- 写入比例 (Write ratios): 所有工作负载的
-
执行步骤 (Execution procedure):
- 预热阶段 (Warm-up stage): 插入所有
KV对,并频繁触发垃圾回收 (GC)和压缩 (compaction)操作,直到系统性能稳定。 - 执行阶段 (Execution stage): 收集性能数据。此阶段持续到总请求大小达到
SSD总容量 (64GB) 的两倍。对于测试的工作负载,此过程总计413小时。
- 预热阶段 (Warm-up stage): 插入所有
5.5. 图像与公式文本摘要(已包含在分析框架的引导说明中,此处不再重复列出)
6. 实验结果与分析
6.1. 核心结果分析
本节详细分析了 AnyKey 及其增强版 相对于 PinK 在各种工作负载和设备配置下的性能表现。
6.1.1. 尾延迟和 IOPS 性能
下图(原文 Figure 10)比较了在 5种低值键比 (low-v/k) 和 2种高值键比 (high-v/k) 工作负载下,三种系统(PinK、AnyKey、)的 95th百分位读取尾延迟 (95th percentile read tail latencies) 的 累积分布函数 (CDF):
该图像是图表,展示了不同日志大小对 ZippyDB、UDB 和 ETC 的 IOPS 及页面写入总数的影响。图(a)显示了在不同日志大小下的 IOPS,而图(b)则展示了页面写入的总数。
-
针对
low-v/k工作负载 (Figure 10(a)-(e)):PinK的尾延迟相当长,而AnyKey和 显著缩短了尾延迟。这证实了AnyKey设计通过最小化元数据大小并使其驻留在设备内部动态随机存取存储器 (device-internal DRAM)中的有效性。 -
针对
high-v/k工作负载 (Figure 10(f)-(g)):AnyKey表现出与PinK相当的短延迟,表明AnyKey也适用于这些工作负载。 的结构设计与AnyKey相同,因此观察到相似的延迟分析结果。下图(原文 Figure 12)展示了三种系统在所有测试工作负载下实现的
输入输出操作每秒 (IOPS):
该图像是图表,展示了KV存储的三种执行模型的比较(a-c),以及KV-SSD的内部架构(d)。其中,图(d)显示了用于定位KV对的元数据结构,包括哈希表和LSM树等。 -
针对
low-v/k工作负载:AnyKey相较于PinK,IOPS平均提升了3.15倍。这一显著提升主要归因于两个关键因素:(i)读取请求 (read requests)的闪存访问 (flash access)次数减少(如 Figure 11b 所示),以及 (ii)压缩 (compaction)开销的降低(详见下一节)。 -
针对
high-v/k工作负载:AnyKey和PinK在不同工作负载下互有胜负。然而, 优于两者,因为它有效避免了压缩链 (compaction chain)的发生。
6.1.2. 元数据 大小及其对 闪存访问 的影响
为了解释 AnyKey 性能提升的原因,论文分析了 元数据 大小及其对 闪存访问 的影响。下图(原文 Figure 11)展示了 AnyKey 和 的 元数据 大小分析及其影响:
该图像是图表(a)和(b),展示了不同值尺寸与键尺寸比率下,95th百分位尾延迟和IOPS的性能特征。其中(a)展示了延迟的CDF曲线,(b)展示了不同比率下的IOPS值。
AnyKey的元数据管理 (Figure 11a):层级列表 (level lists)由于其极小的尺寸,完全容纳在DRAM中。即使是大量的哈希列表 (hash lists)也在剩余的DRAM空间中生成和存储。闪存访问次数 (Figure 11b): 结果是,在大多数情况下,读取操作 (read operation)的闪存访问次数可以限制在最多 2 次。这意味着,即使目标值 (value)存储在值日志 (value log)中,AnyKey也只需要两次闪存访问——一次用于数据段组 (data segment group)中的目标KV实体 (KV entity),另一次用于值日志中由KV实体指向的值。
6.1.3. 压缩 和 垃圾回收 (GC) 分析
下表(原文 Table 3)列出了三种系统在 压缩 和 垃圾回收 (GC) 操作期间产生的页面读写次数:
| Workload | Compared systems | The number of page reads or writes | |||
| Compaction | GC | ||||
| Read | Write | Read | Write | ||
| Crypto1(low-v/k) | PinK | 85M | 88M | 340M | 0 |
| AnyKey | 49M | 26M | 0 | 0 | |
| AnyKey+ | 49M | 26M | 0 | 0 | |
| Cache(low-v/k) | PinK | 41M | 45M | 339M | 0 |
| AnyKey | 64M | 20M | 0 | 0 | |
| AnyKey+ | 48M | 15M | 0 | 0 | |
| W-PinK(high-v/k) | PinK | 3M | 9M | 27M | 0 |
| AnyKey | 25M | 22M | 0 | 0 | |
| AnyKey+ | 20M | 6M | 26K | 26K | |
| KVSSD(high-v/k) | PinK | 0.2M | 10M | 15M | 0 |
| AnyKey | 48M | 50M | 0 | 0 | |
| AnyKey+ | 6M | 9M | 0 | 0 | |
GC操作:AnyKey和 几乎没有GC读写操作。这是因为一个层级的数据段组倾向于存储在相同的块 (blocks)中,并且这些块中的组在压缩期间会一起重新定位。因此,受害者块 (victim blocks)中很少发现有效页 (valid pages)。low-v/k工作负载下的压缩:PinK在low-v/k工作负载下,压缩期间的读写计数显著增加。这主要是因为大量的元段 (meta segments)必须存储在闪存 (flash)中,在压缩过程中重新定位时会产生大量的页面读写。相比之下,AnyKey消除了元段,从而避免了由此产生的读写。high-v/k工作负载下的压缩: 如果AnyKey遇到压缩链,其压缩开销可能会增加。相比之下, 通过防止压缩链的形成,显著降低了开销。
6.1.4. 设备寿命 (Device Lifetime) 和 存储利用率 (Storage Utilization)
下图(原文 Figure 13)显示了每个系统经历的页面写入总数,这实际上反映了 压缩/GC 写入量:
该图像是示意图,展示了 AnyKey KV-SSD 的结构,包括 DRAM、层级列表、元段和数据段。图中标示了不同的键和地址映射,突出显示了键值对在存储中的布局。关键公式如 PPA 代表物理页面地址。
平均比 PinK 减少了 50% 的写入次数。这直接延长了 固态硬盘 (SSD) 的 设备寿命。
下图(原文 Figure 14)显示了当存储已满时,三种系统的 存储利用率(独特 KV对 (KV pairs) 的总大小对整个存储容量的贡献):
该图像是图表,展示了不同元数据类型的大小及其在DRAM或Flash中的位置。图的左侧部分(a)比较了高v/k和低v/k工作负载下数据结构的大小,标出了64MB DRAM的参考线。右侧部分(b)显示了不同请求下Flash的访问次数比例,揭示了在不同工作负载下的性能差异。这些信息有助于理解KV-SSD设计在不同场景下的表现。
- 针对
low-v/k工作负载:PinK需要在闪存 (flash)中维护大量的元段 (meta segments),这意味着它在闪存中为每个键 (key)存储了两个不同的副本(一个来自元段,另一个来自数据段 (data segment))。 - 针对
AnyKey和 : 通过移除元段,它们始终在闪存中为每个键只保留一个副本,因此在low-v/k工作负载下具有更高的存储利用率。
6.2. 敏感性分析
6.2.1. 不同 DRAM 大小下的读取延迟
下图(原文 Figure 15)展示了在 3种代表性工作负载 下,当 设备内部动态随机存取存储器 (DRAM) 容量从 32MB 变化到 96MB 时,AnyKey 经历的 尾延迟 (tail latencies):
该图像是示意图,展示了 AnyKey 设计中的关键-值 SSD 结构。图中包含了 DRAM、Flash 存储的层次结构,以及如何在不同层次中搜索给定关键字的过程。图示强调了级别列表和哈希列表的组合,以及数据段组的排序机制。
low-v/k工作负载 (如Crypto1,ETC): 在元数据较大时,如果DRAM大小从96MB减少到32MB,尾延迟会增加。这是因为即使少量元数据也无法容纳在DRAM中。high-v/k工作负载 (如W-PinK):元数据通常较小,因此微小的DRAM(32MB) 也足以容纳它,延迟变化不明显。
6.2.2. 不同 闪存页 (Flash Page) 大小下的读取延迟
下图(原文 Figure 16)展示了在 3种代表性工作负载 下,当 闪存页 大小从 4KB 变化到 16KB 时,AnyKey 经历的 尾延迟:
该图像是示意图,展示了两种类型的压缩操作:树触发压缩和日志触发压缩。在树触发压缩中,当目标源达到其阈值时,数据段组和价值日志发生合并;而在日志触发压缩中,若日志满则进行合并和回收操作。
- 观察结果:
页面大小 (page size)越大,尾延迟越短。 - 原因: 假设总
固态硬盘 (SSD)容量固定,随着页面大小的增加(意味着闪存页总数减少),AnyKey中的数据段组 (data segment group)数量减少,这反过来意味着层级列表 (level list)条目(元数据大小)减少。更少的元数据使得DRAM能容纳更多,减少闪存访问。
6.2.3. 不同 键分布 (Key Distributions) 下的延迟
在默认 \theta=0.99) 之外,论文还评估了 AnyKey、 和 PinK 在不同 值下的表现( 值越低,键 分布越均匀)。下图(原文 Figure 17)展示了 ETC 工作负载在不同 键分布 下的 延迟 (latencies):
该图像是一个示意图,展示了 AnyKey 中的日志触发压实过程中的问题情况(a)和修改后的日志触发压实方案(b)。图中说明了在源目标满时的处理步骤,以及阈值监控机制的变化。
PinK: 随着键分布变得更均匀,PinK的尾延迟变长。这是因为在更均匀的分布中,许多请求会流向日志结构合并树 (LSM-tree)的较低层级,而这些层级的元数据 (metadata)通常存储在闪存 (flash)中。AnyKey和 : 它们通过减小元数据大小,能够在DRAM中找到这些较低层级键的元数据,因此在不同的键分布下提供了更一致的性能。
6.2.4. 范围查询 (Range Queries) 性能
为了评估 扫描请求 (scan requests) 的性能,论文基于 UDB 工作负载设计了一个 扫描中心 (scan-centric) 工作负载。下图(原文 Figure 18)比较了三种系统在不同 扫描请求 长度下的 尾延迟:
该图像是图表,展示了不同系统下 百分位延迟的累积分布函数(CDF)。包含七个子图,分别为RTDATA、Crypto1、ZippyDB、Cache15、Cache、W-PinK及KVSSD,展示了它们在不同延迟下的表现。
- 观察结果:
扫描请求包含的子请求越多,AnyKey和 带来的效益越显著。 - 原因:
AnyKey和 以数据段组 (data segment group)为单位管理一组连续的键,这有助于扫描的许多子请求从相同的闪存页 (flash pages)和数据段组中得到服务。 - 对比
PinK:PinK中的KV对 (KV pairs)并非排序聚簇在闪存中,而是分散在不同的闪存页中,导致每个子请求可能访问不同的闪存页,性能受限。 - 小型
范围查询: 对于小型范围查询,AnyKey也能表现出与PinK相当的性能,因为它可以使用存储在数据段组第一个页面中的位置信息直接定位目标KV对。
6.2.5. 值日志 (Value Log) 大小对性能的影响
为了评估 值日志 (value log) 大小的影响,论文进行了敏感性分析,将其大小从 3.2GB 变化到 9.6GB(占 64GB SSD 的 5% 到 15%)。下图(原文 Figure 19)展示了不同 值日志 大小对 ZippyDB、UDB 和 ETC 的 输入输出操作每秒 (IOPS) 和 页面写入总数 (total page writes) 的影响:
该图像是图表,展示了不同数据结构的大小及其在元数据中的位置(DRAM或Flash)。图(a)分析各数据结构的大小,图(b)则展示了读取时所需的Flash访问次数,能够反映出AnyKey和AnyKey+在元数据处理上的表现与影响。
IOPS(Figure 19a):- 当
值 (value)大小相对较小 (ZippyDB) 时,即使是小的值日志(如3.2GB)也能实现高IOPS,且随着值日志大小增加IOPS不再显著提升。 - 随着
值大小增加 (UDB和ETC),值日志大小的增加可以略微提高IOPS。 - 分析: 如果工作负载的
值大小较小(例如低值键比 (low-v/k)工作负载),即使是小的值日志也很少会变满,因此很少触发日志触发压缩 (log-triggered compaction)。
- 当
页面写入总数(Figure 19b): 观察到与IOPS相似的模式。- 与
AnyKey-的比较: 论文还考虑了一个未引入值日志的系统AnyKey-。观察发现:(i) 随着写入比例 (write ratio)的增加,AnyKey-的IOPS显著下降,而 仍能保持高IOPS;(ii) 尽管 相对于AnyKey-增加了尾延迟 (tail latencies),但它仍与PinK相当。
6.2.6. 设计可伸缩性 (Design Scalability)
尽管主要假设 64GB SSD 进行研究,但 AnyKey 提案适用于任何 SSD 容量。此外,SSD 容量越大(即 SSD 包含的 KV对 越多),在 低值键比 (low-v/k) 工作负载下,AnyKey 带来的效益就越大。例如,如果 Crypto1 在 4TB SSD 上执行,AnyKey 的 元数据 大小限制在 3.65GB,而 PinK 的 元数据 大小将增加到 25.2GB。这表明 AnyKey 的设计具有良好的可伸缩性。
6.2.7. 多工作负载执行场景 (Multi-Workload Execution Scenarios)
除了单工作负载场景,AnyKey 也适用于多工作负载场景。如果需要将两个工作负载 共置 (co-locate),可以创建两个 分区 (partitions) [1, 29, 41],使每个 分区 由独立的 固件 (firmware)(PinK 或 AnyKey)管理,并在其各自的 分区 中执行每个工作负载。论文进行了一个 2工作负载 场景(w-PinK + ZippyDB)的实验,通过创建两个均匀 分区 并用 PinK 或 AnyKey 管理。
- 结果: 相比
PinK,AnyKey可以分别将w-PinK和ZippyDB的99.9th百分位尾延迟 (99.9th percentile tail latencies)提高14%和216%。 - 结论: 这表明使用
分区机制 (partitioning mechanism)进行多工作负载场景可以帮助每个工作负载在独立分区上从AnyKey中受益。
7. 总结与思考
7.1. 结论总结
本文提出了一个新颖的 键值对固态硬盘 (KV-SSD) 设计 AnyKey,其核心洞察力基于以下观察:(i) 现有 KV-SSD 的设计原则假设的是 值键比 (value-to-key ratios) 极高的有限工作负载范围;(ii) 实际上存在着其他 值键比 较低类型的工作负载。
AnyKey 旨在解决这些 低值键比 (low-v/k) 工作负载下的性能问题,它通过最小化 元数据 (metadata) 的大小,并确保其能够完全驻留在 固态硬盘 (SSD) 内部 动态随机存取存储器 (DRAM) 中,从而减少了额外的 闪存访问 (flash accesses)。其增强版 进一步提升了 日志结构合并树 (LSM-tree) 的管理效率,通过优化 日志触发压缩 (log-triggered compaction) 过程避免 压缩链 (compaction chain),使得 在 低值键比 和 高值键比 (high-v/k) 两种工作负载下都优于 最先进的 (state-of-the-art) 设计 PinK。
通过广泛的真实工作负载评估,AnyKey 在 low-v/k 工作负载下显著改善了 尾延迟 (tail latencies) 和 输入输出操作每秒 (IOPS),而 则在所有类型的工作负载下都表现出卓越的性能,证明了其通用性和高效性。
7.2. 局限性与未来工作
论文主要关注基于 日志结构合并树 (LSM-tree) 的 KV-SSD 设计,这本身是一种选择。以下是论文可能存在的局限性以及未来可能的研究方向:
- 对
LSM-tree结构的依赖:AnyKey是基于LSM-tree的,因此它继承了LSM-tree固有的写放大 (write amplification)和压缩 (compaction)相关的复杂性。尽管AnyKey和 优化了压缩效率,但LSM-tree结构本身仍然是其基础。对于某些不需要LSM-tree复杂性的特定工作负载,可能有更简单的优化方案。 DRAM容量的限制: 尽管AnyKey显著减少了元数据大小,但SSD内部DRAM容量仍然是有限的。对于未来可能出现的极端low-v/k工作负载(例如,键变得极其大,而值变得极其小,导致KV对数量爆炸),即使是AnyKey优化后的元数据也可能再次面临溢出DRAM的风险。值日志 (Value log)的间接性: 引入值日志带来了值访问的间接性,即在读取 (read)操作时可能需要两次闪存访问(一次访问数据段组 (data segment group)中的KV实体 (KV entity)获取值的指针,另一次访问值日志获取实际值)。虽然论文认为这是一种可接受的权衡,并且日志触发压缩有助于将活跃值迁移到数据段组,但对于某些纯读密集 (read-intensive)且值长期保留在值日志中的工作负载,这种间接性仍可能带来轻微的性能开销。哈希冲突位 (Hash collision bits)的开销: 尽管论文指出哈希冲突 (hash collision)发生率极低,但哈希冲突位的存在和处理逻辑增加了设计的复杂性,并在极少数情况下仍可能导致额外的闪存访问。- 模拟环境的局限性: 实验是在
FEMU模拟器上进行的,而非真实KV-SSD硬件。尽管FEMU旨在提供准确的模拟,但实际硬件的复杂性(如更细致的闪存特性、控制器内部并行性、热管理等)可能带来模拟中未完全捕获的因素。 范围查询的优化潜力:AnyKey为范围查询引入了额外的定位信息,并存储在数据段组的第一个页面中。虽然这提高了范围查询的效率,但如何进一步优化或动态调整这种辅助信息的粒度,以适应不同范围查询模式的需求,仍有探索空间。
7.3. 个人启发与批判
7.3.1. 个人启发
- 工作负载特征化的重要性: 这篇论文最核心的启发在于强调了深入理解工作负载特征(特别是
键和值的相对大小,即值键比 (value-to-key ratio))对于存储系统设计的重要性。许多最先进的 (state-of-the-art)设计可能在通用或特定假设下表现优异,但在未考虑到的工作负载(如低值键比 (low-v/k))下却会暴露出严重的性能瓶颈。这提醒研究者和工程师,设计通用系统需要更全面的工作负载建模。 元数据优化的创造性:AnyKey通过将KV对 (KV pairs)组织成数据段组 (data segment groups),并利用哈希值 (hash values)进行组内排序和元数据压缩,极大地减少了DRAM中元数据的存储需求。这种“以组为单位”的元数据策略非常巧妙,它在不牺牲KV对定位效率的前提下,解决了DRAM容量限制的问题,特别是在键较大的场景下。键值分离 (Key-Value Separation)的新视角:值日志 (value log)的引入是键值分离思想在KV-SSD和LSM-tree背景下的一个优秀实践。它不仅减少了压缩 (compaction)过程中的闪存写入 (flash writes)量,延长了设备寿命 (device lifetime),还通过将活跃值 (active values)保留在值日志中,避免了在LSM-tree各层级间值的频繁移动。这种分离和动态管理策略,对于写密集 (write-intensive)工作负载的日志结构合并树具有普遍的借鉴意义。压缩链 (Compaction Chain)问题的识别与解决: 针对LSM-tree中可能发生的压缩链问题提供了实用的解决方案。在日志触发压缩 (log-triggered compaction)过程中通过监控目标层级大小并回写值的策略,有效地中断了压缩链,维护了系统性能的稳定性。这表明在设计复杂的存储系统时,不仅要考虑理想情况下的效率,还要关注异常或连锁反应。
7.3.2. 批判与改进方向
值日志动态管理策略的深入研究:AnyKey简单地将SSD剩余容量的一半用于值日志,并优先选择包含最多无效值 (invalid values)的层级进行日志触发压缩。未来可以研究更智能、更动态的值日志大小分配和值迁移策略。例如,基于工作负载的读写比例 (read/write ratios)、值的访问模式(热点值)、键的生命周期等,动态调整值日志的大小或值迁移的阈值,以进一步优化性能和存储利用率 (storage utilization)。哈希值长度与碰撞率的权衡: 论文指出32位哈希值足以在数据段组中唯一标识键,且哈希冲突发生率低。但随着SSD容量和数据段组中KV对数量的增加,哈希值长度的选择是一个关键的权衡点。未来可以探索自适应的哈希值长度,或者结合更复杂的哈希算法,在保证唯一性的同时,最小化哈希值的存储开销和计算开销。- 更通用的
元数据溢出管理: 尽管AnyKey努力将元数据保持在DRAM中,但在极端情况下(例如,DRAM容量极其有限或KV对数量空前庞大),元数据仍可能溢出到闪存。在这种情况下,如何高效地管理溢出元数据,例如采用多级元数据缓存、或者像PinK那样将部分元段存储到闪存但采用更优化的访问模式,将是值得研究的方向。 - 真实硬件验证: 尽管
FEMU提供了准确的模拟,但最终的性能和效率仍需在真实KV-SSD硬件上进行验证。这将有助于发现模拟器可能未捕获的实际硬件行为和瓶颈,例如更复杂的闪存磨损机制、控制器固件的内部细节以及不同NAND技术的差异。 - 与新兴存储技术的结合: 随着
计算存储 (Computational Storage, CS)和区命名空间 (Zoned Namespace, ZNS)等新兴SSD接口和技术的发展,AnyKey的设计理念如何与这些技术结合,以实现更深层次的协同优化,也是一个潜在的未来研究方向。例如,ZNS可以提供更严格的写入 (write)顺序性,可能进一步简化值日志的管理。
相似论文推荐
基于向量语义检索推荐的相关论文。