关于持久化:Xline-持久化存储设计与实现
01、引言在 Xline 晚期的原型阶段,咱们采纳了基于内存的存储来实现数据的长久化。这尽管简化了 Xline 原型设计的复杂度,进步了我的项目的开发和迭代速度,但带来的影响也是显著的:因为数据都存储在内存当中,因而一旦当过程 crash 后,节点的数据恢复须要依赖于从其余失常节点上拉取全量数据,这就须要较长的复原工夫。基于此方面的思考,Xline 在最新公布的版本 v0.3.0 中引入了一个 Persistent Storage Layer,来将数据长久化到磁盘当中,同时向下层调用方屏蔽掉无关的底层细节。 02、存储引擎选型目前业界支流的存储引擎根本可分为基于 B+ Tree 的存储引擎和基于 LSM Tree 的存储引擎。他们有着各自的劣势与劣势。 B+ Tree 读写放大剖析B+ Tree 在读取数据时,须要先沿着根节点,逐渐向上层索引,直到最初拜访到最底层的叶子结点,每层拜访对应了一次磁盘 IO。而写入数据时,同样也沿着根节点向下搜寻,找到对应的叶子结点后写入数据。 为了不便剖析,咱们进行相干约定,B+ Tree的block size为B,故每个外部节点蕴含O(B)个子节点,叶子节点蕴含O(B)条数据,假如数据集大小为N,则B+ Tree的高度为 写放大:B+ Tree的每次insert都会在叶子节点写入数据,不管数据理论大小是多少,每次都须要写入大小为 B 的数据块,因而写放大是 O(B)读放大:B+ Tree的一次查问须要从根节点一路查到具体的某个叶子节点,所以须要等于层数大小的I/O,也就是, 即读放大为 LSM Tree 读写放大剖析LSM Tree 在数据写入时,先以文件追加的模式写入一个内存文件 memtable(Level 0),当 memtable 达到固定大小时,将其转换成 immutable memtable,并合并到下一个 level 中。而对于数据的读取,则须要先在 memtable 中进行查找,当查找失败时,则向下逐层查找,直到找到该元素为止。LSM Tree 常采纳 Bloom Filter 来优化读取操作,过滤掉那些不存在于数据库中的元素。假如数据集大小为N,放大因子为k,最小层一个文件大小为B,每层文件的单个文件大小雷同都为B,不过每层文件个数不同。写放大:假如写入一个 record,在本层写满 k 次后会被 compact 到下一层。因而均匀单层写放大应为。一共有层,故写放大为 读放大:最坏的状况下,数据被 compact 到最初一层,须要顺次在每一层进行二分查找,直到在最初一层找到.对于最高层 ,数据大小为 O(N), 须要进行二分查找,须要 次磁盘读操作对于次高层 , 数据大小为 , 须要进行 次磁盘读操作对于 , 数据大小为 ,须要进行 次磁盘读操作……以此类推,最终读放大为 R = ...