CSE_lecture7:System modelling + KFS

System modelling & Key-value stores(KVS)

key-value store abstraction

key-value使用唯一的key来标识value,提供接口为get, scan, update, insert, delete,比文件系统更简单

一种想法是可以直接在filesystem上封装一层key-value store的API,key认为是文件名,value为文件的内容。使用system modelling来进行量化

system modelling

在设计系统前,建立其内部模型抽象,提炼出决定系统行为的主要组成部分,实现定性模型。相较于直觉更科学,相较于实验更加高效和普适(但不代表就不用实验了)

现在使用定性模型(qualitative system model)来分析使用filesystem的key-value store:

  • 定义系统的目标:低延迟,并使用少量空间存储更多的数据

  • 分析:以Insert为例,为CREATE + WRITE,共两次system call,并将system call进一步展开

    现在只要知道disk read/write的latency就可以在不实现具体系统的情况下进行分析。

结论是并不高效,额外的操作太多。但实际上在value特别大时还是能够接受的。因此在system modelling时需要考虑参数(parameterized),如static parameters(如disk read/write time), input parameters(如key-value sizes), runtime parameters

一般来说,key-value store用于数据大小很小的时候,因此不考虑该实现,即理想状况下只进行一次block write;另一方面这也造成了很大的空间浪费

build key-value store system

核心想法是:将多个key-value放到同一个文件中,减少空间浪费和延迟

使用filesystem而不是直接进行disk操作是因为这样更加方便,同时兼容性好

step 1: a naive key-value storage

将所有的key-value都放在一个单一文件中,以update为例,有两种方法:

  • file in-place write: 根据offset进行file write来修改,这需要一次random disk write
  • file append: 在文件末尾追加更新值,这一般只需要进行一次sequential disk write

比较之后,append更加高效。

insert和update类似,而delete则会append一个NULL entry,后续进行垃圾回收

step 2: log-structure key-value stores(L-KVS)

log-structured file是append-only的

此时get操作难以高效实现,需要倒序遍历文件

step 3: L-KVS + index

加一层index组件,用于key -> offset的映射,这一层不需要持久化

step 3.1: in-memory hash index + log-structured data file

在内存维护一个map来实现key -> byte offset,问题在于index能否在内存中放下,因此需要允许index放在磁盘上

step 4: L-KVS + (in-memory & disk hybrid index)

使用fat pointer,其既可以指向虚拟内存地址,也可以指向文件的offset

当index既可能在内存中,也可能在磁盘中时,可能导致多次磁盘访问,甚至导致随机磁盘访问,因此不能使用linked-list-based hashing,改进方法为:

  • 一个entry放入多个key,减小链的长度
  • 使用更高级的hashing方法,如cuckoo hashing

目前的架构还有以下问题:

  • log file是永远在增大的,最终导致磁盘空间用尽
  • 不支持范围查找

使用compaction来防止log file无限增大,即通过压缩来删除重复的数据,但当文件特别大的时候相当耗时

因此将文件分为多个segment,compaction时挑选一部分segment,并以segment的粒度来进行压缩,同时在segment之间进行merge;在compaction时还能顺便进行垃圾回收,实现删除。此时模型更加复杂了,在compact/merge时进行get性能会受限,因此建模时还需要考虑compact/merge的频率

step 4.1: L-KVS(w/ compaction & merging) + (in-memory & disk hybrid hashing index)

此时还是没有解决范围查找的问题。解决方法为使用B+树作为index,实现key的排序和高效的范围查找,但这和log-structured file不太兼容

step 5: B+ tree-based KVS

B+树中,update/insert需要多次磁盘访问,尤其是随机磁盘访问;但范围查找效果很好

step 6: SSTables(sorted string table) KVS

SSTable基于segmented log file,同时有两个更新:

  • 每个segment中的key都排好序
  • segment不可修改,因此不是append-only

SSTable的好处在于:

  • key的查找很高效:index只存放一部分key的offset,实际查找时夹逼即可
  • 支持segment里的范围查找

使用memtable来实现内存的修改,从而将SSTable的修改batch在一起。以insert为例:

  • 在memtable中insert
  • 当memtable大到一定程度后,排序并写入SSTable
  • 当SSTable过多时,进行compact + merge

而查找时,先在memtable查找,再依序查找SSTable,可以在每个SSTable上保留一个稀疏的in-memory index来进行优化

范围查找则需要segment之间也进行排序

SSTable不应当简单地顺序存储,因此还需要优化

step 7: LSM trees

将SSTable摆放为多层架构,除了L0之外,每层的文件都排好序,且没有重复的key;上层的数据比下层的数据更新

任何系统都可能出现corner case,比如LSM tree可能出现写阻塞(write stall),这是因为前一次写入过于耗时(多次compact)导致的

对于错误处理,比如memtable丢失,可以使用log来恢复memtable

相较于B+ tree,好处是写的性能更好,坏处是range性能稍差


CSE_lecture7:System modelling + KFS
http://example.com/2025/10/19/CSE-lecture7-System-modelling-KFS/
作者
jietiDdd
发布于
2025年10月19日
许可协议