北方的南先生
北方的南先生 今天的我甚至凌驾于阿修罗
2021年07月26日入驻 合计 3 个作品 累计 4.54 万字 共有 1 订阅
  • 基本概念

    leveldb是一个写性能十分优秀的存储引擎,是典型的LSM树(Log Structured-Merge Tree)实现。LSM树的核心思想就是放弃部分读的性能,换取最大的写入能力。

    LSM树写性能极高的原理,简单地来说就是尽量减少随机写的次数。对于每次写入操作,并不是直接将最新的数据驻留在磁盘中,而是将其拆分成(1)一次日志文件的顺序写(2)一次内存中的数据插入。leveldb正是实践了这种思想,将数据首先更新在内存中,当内存中的数据达到一定的阈值,将这部分数据真正刷新到磁盘文件中,因而获得了极高的写性能(顺序写60MB/s,随机写45MB/s)。

    在本文中,将介绍一下leveldb的基本架构、概念。
  • 读写操作

  • 日志

    为了防止写入内存的数据库因为进程异常、系统掉电等情况发生丢失,leveldb在写内存之前会将本次写操作的内容写入日志文件中。
  • 内存数据库

    leveldb中内存数据库用来维护有序的key-value对,其底层是利用跳表实现,绝大多数操作(读/写)的时间复杂度均为O(logn),有着与平衡树相媲美的操作效率,但是从实现的角度来说简单许多,因此在本文中将介绍一下内存数据库的实现细节。
  • sstable

    如我们之前提到的,leveldb是典型的LSM树(Log Structured-MergeTree)实现,即一次leveldb的写入过程并不是直接将数据持久化到磁盘文件中,而是将写操作首先写入日志文件中,其次将写操作应用在memtable上。

    当leveldb达到checkpoint点(memtable中的数据量超过了预设的阈值),会将当前memtable冻结成一个不可更改的内存数据库(immutablememory db),并且创建一个新的memtable供系统继续使用。

    immutable memory db会在后台进行一次minorcompaction,即将内存数据库中的数据持久化到磁盘文件中。

    注解

    在这里我们暂时不展开讨论minorcompaction相关的内容,读者可以简单地理解为将内存中的数据持久化到文件

    leveldb(或者说LSM树)设计Minor Compaction的目的是为了:

    有效地降低内存的使用率;
    避免日志文件过大,系统恢复时间过长;当memorydb的数据被持久化到文件中时,leveldb将以一定规则进行文件组织,这种文件格式成为sstable。在本文中将详细地介绍sstable的文件格式以及相关读写操作。
  • 缓存系统

    缓存对于一个数据库读性能的影响十分巨大,倘若leveldb的每一次读取都会发生一次磁盘的IO,那么其整体效率将会非常低下。

    Leveldb中使用了一种基于LRUCache的缓存机制,用于缓存:

    已打开的sstable文件对象和相关元数据;
    sstable中的dataBlock的内容;

    使得在发生读取热数据时,尽量在cache中命中,避免IO读取。在介绍如何缓存、利用这些数据之前,我们首先介绍一下leveldb使用的cache是如何实现的。
  • 布隆过滤器

    BloomFilter是一种空间效率很高的随机数据结构,它利用位数组很简洁地表示一个集合,并能判断一个元素是否属于这个集合。BloomFilter的这种高效是有一定代价的:在判断一个元素是否属于某个集合时,有可能会把不属于这个集合的元素误认为属于这个集合(falsepositive)。因此,BloomFilter不适合那些“零错误”的应用场合。而在能容忍低错误率的应用场合下,BloomFilter通过极少的错误换取了存储空间的极大节省。

    leveldb中利用布隆过滤器判断指定的key值是否存在于sstable中,若过滤器表示不存在,则该key一定不存在,由此加快了查找的效率。
  • compaction

    Compaction是leveldb最为复杂的过程之一,同样也是leveldb的性能瓶颈之一。其本质是一种内部数据重合整合的机制,同样也是一种平衡读写速率的有效手段,因此在下文中,首先介绍下leveldb中设计compaction的原由,再来介绍下compaction的具体过程。
  • 版本控制

    Leveldb每次新生成sstable文件,或者删除sstable文件,都会从一个版本升级成另外一个版本。

    换句话说,每次sstable文件的更替对于leveldb来说是一个最小的操作单元,具有原子性。

    版本控制对于leveldb来说至关重要,是保障数据正确性的重要机制。在本文中,将着重从版本数据的格式以及版本升级的过程进行展开。
  • 创建/打开/关闭数据库 - Opening A Database

  • 读写更新数据库

  • 并发/迭代/快照

  • Slice - LevelDB使用的数据结构

  • 比较器 - Comparators

  • 性能 - Performance

  • 校验和 - Checksums

  • 常见问题及实践

  • Go 的垃圾回收器 Mark And Sweep算法

  • 常见的垃圾回收算法

  • 什么是三色标记法