搜索引擎那样的,如Lucene, MDS等,先build index,然后用index提供查询服务。index是基于某一时刻的snapshot的index,是滞后的并不实时反应数据的变化。
内存数据结构,如平衡树,hashtable等,不是persistent的
类似数据库那样的,用B+树在磁盘上组织数据,是一个可选方案,缺点是虽然B+树已经很低,但是因为是基于磁盘的,每一次都是disk seek,仍然不够高效
MemTable + SSTable方案:
SSTable链 + MemTable代表了更新历史,memTable是最新的
写:先写commit log(redo log), 保证persistent,然后写memTable,
Minor Compact:当memTable满了,写到一个新的SSTable, 保存 redo log的 recovery point
读:先读MemTable, 然后从后往前读SSTable,直到找到key
删除:只是用tombstone标记可以GC,真正删除是在Major Compact
Major Compact:后台定时merge SSTable,整理的时候真正删除标记为delete的key(有点java GC的意思)
恢复:从前往后读SSTable,做merge,形成一个memTable,然后apply recover point 之后的redo log。
读写性能分析:耗时的部分主要在于读写磁盘,顺序读写又好于random读写(disk seek)
写:耗时的部分就是在于写commit log,因为是写磁盘。但commit log是只append的文件,不需要做disk seek,而B+树要一般都会navigate若干次。这样,即快,又persistent。
读:一般的情况,key并不在MemTable里,而是在某个SSTable里。均摊情况下,SSTable的 index(pointer table)可以认为是已经在内存了,这样,只要从后往前依次做几个binary search就可以找到key,然后做一次 disk seek就可以了。 增强:BloomFilter 处理key不存在的情况, scan cache对读取多次相同的key,block Cache对读取相邻key可以有很好的支持。
SSTable的结构 和MDS master bin结构比较
相同点:都是一个一个key, value记录顺序存入,最后append一个index (pointer table)
不同点:1)SSTable的 index 不是per record的,而是per block的,MDS master是per key的
2)SStable是有序结构MemTable flush出来的,有序,而且基于块的索引也需要有序,支持range查询。MDS的 master虽然也是按lableIndex递增的,但本质上是堆表,只支持点查询。