Bitcask-一个用于快速键/值数据的日志结构哈希表

原论文链接:https://riak.com/assets/bitcask-intro.pdf

Bitcask的起源与Riak分布式数据库的历史密切相关。在Riak键/值集群中,每一个节点使用可插拔式的本地存储;几乎一切k/v-形的存储引擎都可以被用来作为每一个主机的存储引擎。这种可插拔性允许Riak的处理并行化,这样存储引擎可以在不影响其它代码库的情况下去做改进和测试。

许多这样本地的键/值存储已经有了,包括但不限于Berkeley DB, Tokyo Cabinet 以及Innostore.在评估此类存储引擎的时候,我们寻求了许多目标,包括:

  • 每个条目读或写低延迟
  • 高吞吐量,尤其是在写随机条目的输入流时
  • 有处理比RAM大得多的数据集的能力并不会降级
  • 崩溃友好,既要快速恢复又要数据零丢失
  • 易于备份和恢复
  • 一份相对简单、可理解(因而可支持)的代码结构和数据格式
  • 在高访问负载或大容量的情况下的可预测行为
  • 允许在Riak中轻松默认使用的许可证

实现其中的一些是容易的。但是实现全部就不是那么容易了。

对于上述所有目标,没有一个可用的本地键/值存储系统(包括但不限于作者编写的那些)是理想的。我们与Eric Brewer讨论这个问题的时候,他有一个关于哈希表日志合并的关键见解:那样做和LSM-树一样快,甚至更快。

这使我们以一个新的视角探索了在20世纪80年代和90年代首次的日志结构文件系统用到的一些技术。这场探索导致了Bitcask的开发,这是一种能完美满足上述所有目标的存储系统。虽然Bitcask最初的开发目标是在Riak下使用,但是她是通用的,也可以作为其它应用程序的本地键/值存储。

我们最终采用的模型在概念上非常简单。Bitcask实例是一个目录,我们强制只有一个操作系统进程在给定的时间打开Bitcask进行写入。你可以想象为那个进程实际上就是"数据库服务器"。在任何时候,只有一个文件是"活动"状态用于被服务器来写入。当那个文件达到空间阈值它将被关闭,然后一个新的文件将会被创建。一旦一个文件被关闭,无论是有意关闭或者是服务器退出,这个文件被认为是不可变的并将不会再被打开来写入。

活动文件只通过追加方式写入,这意味着顺序写入不需要磁盘查找。为每个键/值条目编写的格式很简单:

每一次写,一个新的条目会被添加到活动的文件中。注意,删除只是写了一个特殊tombstone的值,它将在下一次合并的时候被移除掉。所以,Bitcask数据文件只不过是这些条目的线性序列。

在增加操作完成后,一个叫做"keydir"的内存结构就被更新了。keydir是一个简单的哈希表,它将Bitcask中的每个键值映射到一个固定大小的结构,给出了该键的文件、偏移量和最近写入的条目的大小。

当发生写操作时,keydir将用最新数据的位置自动更新。旧的数据仍然存在于磁盘上,但是任何新的读取都将使用keydir中提供的最新版本。正如我们稍后看到的,合并过程最终将删除旧值。

读取一个值是很简单的,不需要超过一个磁盘搜素。我们在keydir中查找键,然后从那里使用从查找中返回的文件id、位置和大小读取数据。在许多情况下,操作系统的文件系统预读缓存使这一操作比预期的快得多。

随着时间的推移,这个简单的模型可能会消耗大量的空间,因为我们只是写出了新的值,而没有接触到旧的值。我们称之为“合并”的压缩过程解决了这个问题。合并过程遍历Bitcask中的所有非活动(即不可变)文件,并声称一组数据文件,其中仅包括每个当前键的"活动"或最新版本。

当这个完成后,我们还在每一个数据文件旁边创建一个"提示文件"。它们本质上类似于数据文件,但与值不同的是,它们包含相应数据文件中值的位置和大小。

当Bitcask被一个Erlang进程打开,它会检查去看是否已经有另一个Erlang进程在同一个虚拟内存中也正在使用该Bitcask。如果有,它将和该进程共享这个keydir。如果没有,它会扫描当前目录下所有的数据文件,以便于构建一个新的keydir。对于任何具有提示文件的数据文件,将扫描该文件以获得更快的启动时间。

这些基本的操作是Bitcask系统的本质。显然,我们没有试图在本文中公开操作的每一个细节,我们的目标是帮助您了解Bitcask的一般机制。在我们略过的几个领域上的一些额外注释可能是有序的:

  • 我们提及到,我们依赖于操作系统的文件系统缓存来获得读性能。我们已经在上面讨论过添加一个内部Bitcask的读缓存,但是考虑到我们现在可以免费获得多少里程,现在还不清楚这能带来多少回报。
  • 我们将很快提供针对各种api类似的本地存储系统的基准测试。然而,我们最初使用Bitcask的目标并不是成为最快的存储引擎,而是获得“足够的”速度、高质量和简单的代码、设计和文件格式。也就是说,在我们最初的简单基准测试中,我们已经看到Bitcask在很多情况下都轻松超越了其他快速存储系统。
  • 一些最难实现的细节也是大多数外部人士最不感兴趣的,所以我们没有在这个简短的文档中包括(例如)内部keydir锁定方案的描述。
  • Bitcask不执行任何数据压缩,因为这样做的成本/效益是非常依赖于应用程序。
posted @ 2021-07-23 18:05  丹华抱一鷇音子  阅读(550)  评论(0编辑  收藏  举报