摘要
本文研究了一种能充分利用内置透明压缩能力的现代存储硬件的键值(KV)存储器的设计。许多现代存储设备/驱动器实现了基于硬件的数据压缩,对操作系统和应用程序是透明的。此外,云基础设施中基于硬件的压缩的部署越来越多,导致内置透明压缩的基于云的存储硬件即将到来。通过将逻辑存储空间的使用效率与真实的物理存储空间使用情况解耦,透明压缩允许数据管理软件有目的地浪费逻辑存储空间,以换取更简单的数据结构和算法,从而降低实现复杂度,提高性能。本工作提出了一种无表的基于哈希的KV存储,其基本思想是将密钥空间直接哈希到逻辑存储空间中,而根本不使用哈希表。由于数据结构大为简化,这种方法存在严重的逻辑存储空间利用率不足的问题,而使用透明压缩的存储硬件可以无缝地缓解这一问题。本文介绍了基本的KV库结构,并发展了数学公式来辅助其配置和分析。我们实现了这样一个KV存储KallaxDB,并在一个内置透明压缩的商业SSD上进行了实验。结果表明,虽然只消耗很少的内存资源,但它在吞吐量、延迟和CPU使用方面优于其他现代KV存储。
1介绍
本文提出了一种key-value (KV)存储设计方案,该方案针对日益增长的具有内置透明数据压缩的存储硬件系列进行了优化。商业市场见证了存储设备的兴起,它们实现了基于硬件的数据压缩,对操作系统和应用程序透明。现代全闪光阵列内置了基于硬件的透明压缩。内置透明压缩的商用ssd正在出现。云供应商已经开始将基于硬件的压缩能力集成到他们的存储基础设施中,从而导致带有内置透明压缩的基于云的存储硬件即将到来。
本段总结:内置透明压缩的存储硬件正在快速发展,本文提出的key-value设计方案为内置透明压缩的存储硬件进行了优化。
除了透明地降低存储成本而不影响应用程序性能之外,内置透明压缩的存储硬件还为数据管理软件的创新带来了新的机遇。这项工作表明,这种存储硬件可以将基于哈希的KV存储从维护昂贵的内存哈希表中解脱出来,从而产生了一种新的、高效内存的、无表的、基于哈希的KV存储。其核心是利用这种存储硬件将逻辑存储空间利用效率与物理存储空间利用效率解耦。在传统的存储硬件上运行时,KV 存储单独负责物理存储空间的利用效率。因此,它面临着严格的存储成本和实现复杂度之间的权衡:为了降低存储成本,KV存储必须充分利用逻辑存储空间,用KV对填充每个4KB LBA(逻辑块地址)扇区,这不可避免地需要复杂而昂贵的数据结构和算法。例如,基于哈希的KV存储使用一个需要大量内存的哈希表,以确保在逻辑存储空间上紧凑地放置KV对,从而降低存储成本。基于哈希的KV存储的高内存成本是它在现实世界中的部署与基于内存高效数据结构的KV存储相比相形见绌的主要原因之一。
本段总结:在传统的存储硬件上运行时,KV 存储单独负责物理存储空间的利用效率。因此,它面临着严格的存储成本和实现复杂度之间的权衡。内置透明压缩的存储硬件可以将基于哈希的KV存储从维护昂贵的内存哈希表中解脱出来,从而产生了一种新的、高效内存的、无表的、基于哈希的KV存储。其核心是利用这种存储硬件将逻辑存储空间利用效率与物理存储空间利用效率解耦。
要从根本上克服基于哈希的KV存储的内存成本障碍,唯一的选择是将键空间直接哈希到逻辑存储空间,而根本不使用哈希表。然而,KV对不能再紧密地放置在逻辑存储空间上,导致大量空间未得到充分利用。因此,当在传统的存储硬件上运行时,这种无表KV存储将承受过高的存储成本,因此实际上是不可行的。相反,一旦我们用高度可压缩的内容填充未占用的空间,内置透明压缩的存储硬件就可以在很大程度上保持物理存储空间的利用效率。因此,在内置透明压缩的存储硬件上运行时,无表哈希KV存储可以在不牺牲存储成本的情况下消除内存成本障碍。在实现大容量KV存储时,这可能第一次使基于哈希的方法成为一种可行的替代方法,而不是基于树的方法。
本段总结:要从根本上克服基于哈希的KV存储的内存成本障碍,唯一的选择是将键空间直接哈希到逻辑存储空间,而根本不使用哈希表。然而,当在传统的存储硬件上运行时,这种无表的KV对不能再紧密地放置在逻辑存储空间上,导致大量空间未得到充分利用。因此,实际上是不可行的。但是,在内置透明压缩的存储硬件上运行时,无表哈希KV存储可以在不牺牲存储成本的情况下消除内存成本障碍。
本文提出了一种基于哈希的无表KV存储架构,并开发了一套数学公式来辅助分析和配置。因此,我们在KallaxDB中实现了所提出的设计技术,并将其与RocksDB[28]、WiredTiger[32]和KVell[18]这三个最先进的基于树的KV库进行了比较。使用YCSB基准测试,我们在内置透明压缩的商用PCIe Gen3x4 SSD上进行了实验。结果表明,KallaxDB通过消耗少量的内存资源,在吞吐量、延迟和CPU使用方面优于其他KV存储。例如,在400byte KV大小、400GB数据集和YCSB 50:50的混合读写工作负载下,与RocksDB相比,它的ops/s提高了1.6倍,读时延缩短了1.5倍,单次操作的CPU利用率降低了2.3倍。我们希望,这项工作将有助于吸引更多的研究兴趣,利用内置透明压缩的现代存储硬件来创新未来的数据管理系统。
2背景
为了让用户应用程序无缝地从数据压缩中受益,存储社区已经将透明压缩能力集成到底层IO堆栈(例如,文件系统、块层或存储硬件)中。例如,ZFS[4]和Btrfs[29]支持文件系统级透明压缩,Red Hat Enterprise Linux包含VDO (Virtual Data Optimizer)模块,实现块级透明压缩。然而,软件解决方案会消耗主机的CPU资源,因此在性能和存储成本之间存在权衡。如果我们将数据压缩推进到存储硬件层,系统将不必考虑性能与存储成本之间的权衡。现代的全闪光阵列设备和一些最新的ssd可以支持透明压缩。图1为内置透明压缩的SSD:在SSD控制器内部,硬件在IO路径上进行(解压缩)压缩,FTL (flash转换层)管理所有变长压缩数据块的映射/索引。为了保持良好的随机IO性能,压缩应该以每4kb为基础进行。
图1:内置透明压缩的SSD的示意图。
本段总结:内置透明压缩的SSD:在SSD控制器内部,硬件在IO路径上进行压缩或解压缩,FTL (flash转换层)管理所有变长压缩数据块的映射/索引。将数据压缩推进到存储硬件层,系统将不必考虑性能与存储成本之间的权衡。
如图2所示,内置透明压缩的存储硬件具有以下两个特性:(a)存储硬件可以暴露一个远远大于其内部物理存储容量的LBA空间。(b)由于特殊的数据模式(例如,全零)可以被高度压缩,我们可以留下一个4KB LBA部分填充有效数据,而不浪费物理存储空间。这两个特性将逻辑存储空间利用率与物理存储空间利用率解耦。这允许数据管理软件有意地充分利用逻辑存储空间,以获得性能优势,而不牺牲真正的物理存储成本。
图2:内置透明压缩的存储硬件使逻辑和物理存储空间利用率解耦的示意图。
本段总结:内置透明压缩的存储硬件具有以下两个特性:(a)存储硬件可以暴露一个远远大于其内部物理存储容量的LBA空间。(b)由于特殊的数据模式(例如,全零)可以被高度压缩,我们可以留下一个4KB LBA部分填充有效数据,而不浪费物理存储空间。这两个特性将逻辑存储空间利用率与物理存储空间利用率解耦。这允许数据管理软件有意地充分利用逻辑存储空间,以获得性能优势,而不牺牲真正的物理存储成本。
3 .提出的设计方案
3.1基本概念
在内置透明压缩的存储硬件上,利用解耦的逻辑与物理存储利用效率,我们提出了一种无表、基于哈希的KV存储设计方法,如图3所示。它的基本思想是直接将键空间哈希到逻辑存储空间上,而不需要经过中间散列表。在传统实践中,如图3(a)所示,每个键首先被哈希到哈希表中的一个条目,该条目进一步指向存储空间中KV对的位置。通过中间哈希表,间接映射可以确保在逻辑存储空间上紧密地放置KV对。为了用一个IO来为每个KV GET请求提供服务,哈希表必须完全驻留在内存中,这导致了高昂的甚至难以承受的内存成本。
本段总结:本文利用了内置透明压缩的存储硬件的逻辑存储与物理存储解耦的特点,提出了一种无表、基于哈希的KV存储设计,主要思想是直接将键空间哈希到逻辑存储空间,不需要中间哈希表(完全驻留在内存),这样一方面节省了内存的资源,另一方面充分利用了逻辑存储空间。
内置透明压缩的存储硬件可以完全消除内存中的哈希表,如图3(b)所示。设K表示键空间,L表示KV存储以页面为单位访问的逻辑存储空间。每个页面跨越一个或多个连续的逻辑存储空间。我们用一个哈希函数𝑓𝐾→𝐿散列每个键𝐾𝑖 ∈ K到一页𝐿𝑗 ∈ L。不使用一个哈希表,它消除了基于散列的KV存储的内存成本障碍。此外,通过将CPU从管理/搜索哈希表中解放出来,它消耗的CPU资源更少。同时,如图3(b)所示,所提出的方法存在逻辑存储空间利用率明显不足的问题(即几乎所有的页面都有大量的空空间未被占用)。一旦我们用零填充未占用的空间,具有内置压缩功能的存储硬件就可以保持物理存储空间的高利用率。
图3:提出的无表哈希KV存储设计方法示意图。
3.2 KallaxDB的实现
我们实现了一个名为KallaxDB的无表哈希KV存储,其架构如图4所示。除了那些记录在WAL (预写日志)中的,所有的KV对都保存在两个存储中:基于哈希的主存储存储了绝大多数的KV对,溢出存储存储了不能在基于哈希的主存储中装入它们的目标页面的KV对。让 𝑙𝑝𝑔表示基于哈希存储的页面大小。如果超过𝑙𝑝𝑔大小的KV对被哈希到同一页,我们必须溢出一个或多个KV对到溢出存储。让L表示基于哈希的主存储的总逻辑存储空间。为了提高并行性,我们将L划分为𝑛大小相等的部分,每个部分L𝑗关联一个后台写线程。将一个key(𝐾𝑖∈K)的KV对写入基于哈希的存储中,假设我们有𝑓𝐾→𝐿(𝐾𝑖)=𝐿𝑖∈L𝑗L𝑗,与L𝑗段相关联的后台写线程进行读-修改-写操作(即获取𝐿𝑖的页面,根据写请求修改其内容,并将修改后的页面写回𝐿𝑖)。要从基于主哈希的存储中读取KV对,我们只需简单地计算哈希来查找并获取我们提取所请求的KV对的页面。
图4:KallaxDB架构的说明。
本段总结:KallaxDB的架构说明。除了那些记录在WAL (预写日志)中的,所有的KV对都保存在两个存储中:基于哈希的主存储存储了绝大多数的KV对,溢出存储存储了不能在基于哈希的主存储中装入它们的目标页面的KV对。
KallaxDB在日志结构中实现WAL和溢出存储:每个进入的KV对被附加到一个SSD段,其索引(即密钥和地址)被记录在内存中的B+树中。一旦一个ssd上的WAL段的大小达到一个阈值,这个段将被密封,一个新的ssd上的WAL段将被创建来接收进来的KV对。对于无法装入指定页面的KV对,KallaxDB将它们保存在溢出存储中。后台写线程处理从WAL到基于哈希的主存储的KV迁移,并回收被密封的WAL段占用的存储空间。对于溢出存储的段,它们将在重新哈希过程中被重新扫描(稍后介绍),在此过程中存储空间将被回收。
为了保持页面溢出概率足够低,因此使溢出存储小,我们必须保持适当的|K|: |L|比例,其中,|K|表示键空间K中的key的数量,|L|表示基于哈希存储的逻辑存储空间L中的页数。因此,为了适应运行时|K|的变化,我们应该调整|L|,为此我们必须相应地改变哈希函数𝑓𝐾→𝐿,从而重新哈希整个无表的基于哈希的存储。对于每个重哈希过程,让L𝑜𝑙𝑑和L𝑛𝑒𝑤表示重哈希前后的存储逻辑存储空间。KallaxDB使用一个或多个后台重哈希线程,其中每个线程以批处理模式重哈希KV对:让𝑛𝑏表示批处理大小。在每个批处理过程中,一个rehash线程从L𝑜𝑙𝑑读取𝑛𝑏页面并提取所有KV对,然后使用新的哈希函数对每个KV对进行重哈希,并相应地将KV对写入L𝑛𝑒𝑤中的指定页面。如果在同一批的多个KV对被哈希到L𝑛𝑒𝑤中的同一页,我们可以将它们的重新哈希合并到一个单页写IO中。为了最大化的实现写合并,KallaxDB使用以下策略来生成每个哈希函数:令L𝑀表示一个逻辑存储空间,这个逻辑存储空间大大大于基于哈希的存储空间的最大可能逻辑存储空间,让𝑓𝐾→𝐿𝑀表示一个固定的主哈希函数,在整个KV存储生命周期中,基于这个哈希函数,我们驱动所有的哈希函数。鉴于 |L| 的目标值,定义𝑅𝑠=⌈|L𝑀| / |L|⌉,并构造相应的哈希函数𝑓𝐾→𝐿作为⌊𝑓𝐾→𝐿𝑀/𝑅𝑠⌋。当将逻辑存储空间从L𝑜𝑙𝑑重哈希到L𝑛𝑒𝑤时,每个批处理都重哈希L𝑜𝑙𝑑上多个连续页面中的所有KV对。由于新旧哈希函数仅在除数𝑅𝑠处不同,L𝑜𝑙𝑑上连续页中的KV对将被重哈希为L𝑛𝑒𝑤上连续页中的KV对,这可以最大化写合并。
根据上面的讨论,我们可以总结KallaxDB的主要操作如下:
读:为了用键𝐾𝑖服务读请求,KallaxDB首先通过搜索相应的索引来检查𝐾𝑖是否位于WAL中。如果没有,KallaxDB尝试通过直接哈希从基于哈希的主存储中获取KV对。如果仍然没有找到,KallaxDB将转向溢出存储。由于体积小,WAL和溢出存储可以很容易地将它们的索引完全保存在主机内存中。因此,KallaxDB通过单个存储IO来处理读请求。为了最小化读延迟并兼容典型的KV存储API, KallaxDB通过同步IO服务于读请求。
写:为了满足写请求(插入或更新),就像大多数其他KV存储一样,KallaxDB在WAL中记录写请求,更新WAL索引,然后立即向客户端响应写完成。如图4所示,在后台数据迁移过程中,KV对从WAL被移动到基于哈希的存储(或溢出存储)中。
后台数据迁移:在后台,KallaxDB将KV对从WAL迁移到基于哈希的存储(通过read-modified-write)或溢出存储。由于每个部分关联一个后台写线程,数据迁移可以在所有𝑛部分上并行进行。所有的后台数据迁移都是通过异步IO实现的,以便更好地利用存储硬件的带宽。后台写线程还定期检查是否有需要重哈希的部分文件,并相应地将它们推到重哈希线程中。
后台重哈希:KallaxDB通过应用一个新的哈希函数来重新散列键空间,从而扩展/收缩基于哈希的主存储的逻辑存储空间。为了避免后台写线程和后台重哈希线程之间的争用,当一个section中的一个文件被重哈希时,不会有数据从WAL迁移到这个文件中。只有当文件被完全重新哈希后,新的哈希函数才会用于处理客户端读请求和后台数据迁移。此外,与此文件相对应的溢出存储段也将被重新扫描,其中的kv将被填充到新的重新哈希的逻辑空间中。KallaxDB通过配置批处理大小和重新哈希线程的数量来控制后台重新哈希的速度。
3.3数学公式
本小节介绍了一组数学公式来估计两个重要的KallaxDB操作指标:(1)溢出统计(包括页面溢出概率和溢出存储数据集大小),以及(2)页面填充因子(即有效KV对填充每个页面的满度)。准确地预测这两个指标对于KallaxDB适当地配置基于哈希的主存储的逻辑存储空间至关重要。为了便于数学表述,我们将KV对的大小作为独立和同分布的随机变量贯穿全文。
5。相关工作
由于LSM树具有较高的内存效率,并且很好地匹配了闪存的运行特性,因此基于LSM树构建的KV库受到了学术界的广泛关注并得到了广泛的应用(如RocksDB[28]和Cassandra[1])。之前关于LSM树KV存储的大部分工作都是通过修改数据体系结构来减小写放大。PebblesDB[26]通过开发一个片段LSM树结构来减少写放大。Dostoevsky[9]通过开发一种延迟调平方案来减小写放大,并给出了整个LSM树设计空间的泛化。TRIAD[3]通过动态分离热键和冷键并延迟压缩来减小写放大。Skip-Tree[34]减少了写压缩。VT-tree[31]通过拼接操作减小写放大,避免了对顺序数据进行不必要的数据拷贝。LSM-trie[33]通过整合指数型数据增长模式和线性数据增长模式来减小写放大。通过定制半排序数据的数据结构,SlimDB[27]减少了写放大。X-Engine[15]通过识别和回收在压缩过程中关键范围不与任何其他数据块重叠的数据块,减少了写放大。写放大也可以通过分离key和value的存储来降低,这在之前的工作中已经得到了很好的证明(例如,wickkey[20]和HashKV[6])。Luo和Carey[21]对LSM树KV存储进行了全面的调查。
之前的工作也很好地研究了建立在其他数据结构上的KV存储。SILT[19]跨几种不同的数据结构组织所有KV对,具有不同的性能和成本权衡。Tucana[24]提供了一个建立在改进的B𝜖-tree上的KV存储,结合了几种技术来提高缓存和IO效率。KVell[18]提出了一种基于B-tree的KV存储,采用基于KV大小的数据分区,减少了后台垃圾收集的影响。之前的研究[10,11,16]也研究了基于哈希的KV库的设计,将KV对以对数结构存储在SSD上,通过内存哈希表实现寻址。uDepot[16]将哈希表完全保存在主机内存中,旨在通过用户空间IO堆栈提高IO效率。FlashStore[10]和SkimpyStash[11]提供了降低哈希表的内存成本的技术,而代价是更高的读放大。NVMKV[22]通过将SSD FTL定制与KV库设计深度耦合,实现了一个基于哈希的KV库。相比之下,通过利用内置透明压缩的存储硬件,我们提出的设计方法从根本上消除了基于哈希的KV存储的内存成本障碍。
6. 总结
本文提出了一种无表、基于哈希的KV存储,为具有内置透明压缩能力的现代存储硬件定制。通过解耦逻辑与物理存储空间的利用效率,这种新的存储硬件使KV存储能够有意地充分利用逻辑存储空间,以换取更简单的数据结构和算法,从而实现更高的性能和/或更低的CPU/内存使用。基于这一主题,本文提出的无表哈希KV存储通过将密钥空间直接哈希到逻辑存储空间,完全消除了内存哈希表,同时依靠存储硬件中的透明压缩来保持物理存储的成本效率。本文提出了一套数学公式,可以帮助其配置和分析。实验结果表明,无表哈希KV存储在吞吐量、延迟、CPU和内存使用等方面优于其他现代KV存储。