论文学习:A Host-SSD Collaborative Write Accelerator for LSM-Tree-Based Key-Value Stores
这篇文章讲了利用SSD双接口去优化LSM-Tree写阻塞问题的一个设计。
主要架构
SSD双接口,同时提供块接口和KV接口,KV接口作为写阻塞时的数据缓存接口。可以和KV SSD联系起来。
KVACCEL设计中有两个关键因素,解耦和内聚,解耦将SSD分为块接口和KV接口,并且每个接口都有独立的管理和LSM Tree,聚合侧重于管理存储在混合接口SSD中的数据,就好像它是单个数据库实例一样,包括在回滚操作期间统一主机侧和设备侧的LSM - tree,此外,KVACCEL还维护了一个全局元数据管理器来进行元数据的管理。
在写阻塞的期间,通过KV接口,I/O操作可以绕过文件系统和块层,通过驱动程序钻取一条直达NVMe控制器的路径。该路径提供了一种通过键值接口不间断地服务I / O请求的方法,即使在运行在块接口上的数据库发生写入停顿时也是如此。
为了使用混合接口,数据库每次请求操作时都需要做出使用哪个接口的决策。使用块接口的被标记为Main LSM,使用Key-value接口的被标记为Dev-LSM。Main - LSM由运行在宿主机上的LSM - KVS使用,在没有写停顿时使用块接口服务于写操作。另一方面,Dev - LSM完全运行在混合SSD中,当Main - LSM面临写失速时,Dev - LSM使用密钥值接口作为二级缓存存储。
Detector:检测器定期检查Main - LSM中与写入失速特性相关的3个分量:L0中的SST数量、MT大小和待压缩大小。然后探测器将这些信息报告给控制器,以用于路径确定。
Controller:控制器。控制器利用检测器报告的信息,向正确的接口发出I/O操作。如果Detector报告没有写失速发生,向块接口也就是MainLSM写入,否则向KV接口写入。
MetaData Manager:存储元数据,主要是数据被写入哪个接口,对重定向到Dev - LSM的KV对进行跟踪,这些键值对位置的元数据被捕获在内存中的哈希表中,并用于对未来需要知道某个键值对位置的操作进行成员资格测试。在系统发生故障和元数据管理器数据丢失的情况下,可以通过对键值接口中的每个键值对进行范围扫描来恢复数据。
Rollback Manager:为了将两棵LSM树聚合为一棵,需要将分组后的键值对从Dev - LSM返回给Main - LSM。为了方便起见,回滚管理器根据Main - LSM的竞争状态启动回滚操作。回滚管理器从检测器接收写档存在的信息。
读路径
- 元数据管理器检查Key的位置
- 如果key - value对在Main - LSM中或者Dev - LSM为空,Controller将读操作引导到Main - LSM中。
- 如果在Dev - LSM中找到key - value对,Controller将读操作重定向到Dev - LSM中
写路径
- 检测器检查是否存在写延迟。
- 如果检测到写延迟,控制器通过元数据管理器更新记录,表明键值对现在在Dev - LSM中,并将该对写入Dev - LSM。
- 如果未检测到写入失速,控制器将键值对指令写入Main - LSM
- 如果元数据管理器表示Dev - LSM中已经存在重叠的键值对,则更新记录,表示最新的键值对现在在Main - LSM
实现支持
为了支持具有双接口的存储设备,SSD的逻辑NAND闪存地址空间范围被分解为两个地址范围,如图8所示。一个地址范围用于块接口,另一个地址范围用于键值接口。地址范围由解聚点来定义,解聚点是一个逻辑地址,它定义了一个接口的结束和下一个接口的开始。SSD的控制器根据给定的NVMe命令的操作码,对每个接口发出不同的命令。块接口命令在逻辑地址上执行FTL映射,为块接口分配了空间。键值接口命令从为键值接口分配的逻辑地址空间中分配NAND页。两个接口都利用了现有的针对各自接口类型的NVMe命令集规范。由于FTL分别为每个接口映射逻辑地址空间,因此两个接口之间不存在逻辑NAND页重叠的问题。当为块接口创建文件系统时,文件系统只看到为块接口分配的地址范围,并报告存储容量以反映该地址范围。同样,密钥值接口只会存储达到其分配地址范围限制的密钥值对
多租户支持:在单台设备上创建多个孤立区域的能力是多租户环境中的关键需求。块接口上的多租户由NVMe标准规定的名字空间支持,而先前在键值接口上支持名字空间的工作[ 37 ]与KVACCEL的键值接口实现是兼容的。通过同时使用每个接口的命名空间实现和为每个租户匹配两个接口的命名空间,KVACCEL可以完全支持同时使用两个接口的多租户需求。
回滚操作:为了将两个分离的LSM - KVS返回到单一的数据库中,需要将Dev - LSM中缓存的键值对返回到Main - LSM中。这是在一个叫做回滚的过程中完成的.
回滚调度:主要是两种,急切的调度和懒惰的调度,急切的调度适合于读密集的workload,因为devLSM的点读速度要小于MainLSM。一个懒惰的回滚方案在确定没有其他工作负载会干扰或者受到回滚干扰的情况下会触发回滚。该方案是针对写密集型工作负载设计的,因为保持Dev - LSM中的键值对不会有太大的代价。
基于迭代器的大范围扫描:迭代器首先识别整个Dev - LSM的范围,利用Dev - LSM的开始和结束键执行范围查询。4迭代器将搜索整个Dev - LSM,并将5个缓存键值对批量序列化,通过设备内存使用NAND传输到主机,然后将键值对以512 KB的分块保存到系统内存中,以便主机使用直接内存访问( Direct Memory Access,DMA )访问键值对。该尺寸被选为512 KB,是DMA在本平台上支持数据传输的最大尺寸单元。最后,在Main - LSM中,主机可以检索并解包key - value对以合并回来。8在一次回滚操作结束后,对Dev - LSM进行重置,以防止下一次回滚操作中的一致性问题。
因为写阻塞的时间很短,所以Dev LSM中的SST不会很多,可以保证每次回滚操作都在写阻塞时完成。
范围查询:范围查询工作结合了KVACCEL中各个接口的迭代器实现。MainLSM可以使用选择的LSM - KVS实现迭代器和范围扫描。同时,Dev - LSM的密钥值接口具有对迭代器和范围扫描功能的支持,然后采用与回滚类似的操作,在两个LSM Tree上通过迭代器的Seek()和Next()去完成范围查询。