SeaweedFS提供了几种不同的needle索引策略,包括memory, btree, blotdb, leveldb四种,其中默认的是memory,也是其内部唯一自己实现的一种索引,btree使用google的btree开源实现,boltdb和leveldb都依赖一个db.
memory的索引实现,使用了一个叫CompactMap(这是作者自己起的名)的数据结构。本文后面将会重点介绍compactMap是一个怎样的数据结构,以及如何使用这个数据结构简历needle的索引。
CompactMap
compactMap本质是一个数组(Golang中可以动态扩展的数组),其元素类型是CompactSection,定义如下:
//This map assumes mostly inserting increasing keys
type CompactMap struct {
list []*CompactSection
}
CompactMap结构体内部只有一个CompactSection的结构体的指针数组,那么为什么作者假设插入的key是增序的呢?我们先看CompactSection是一个什么样的结构,答案后面就会很清楚。
下面是CompactSection的结构:
type CompactSection struct {
sync.RWMutex //读写锁
values []NeedleValue //NeedleValue数组,保存了Needle的key, offset, size
overflow map[Key]NeedleValue //用于保存超出batch,但是在(start, end)范围的needleValue
start Key //该section保存的key最小值
end Key //该section保存的key最大值
counter int //当前该section的needleValue的数量
}
CompactSection保存了key值在[start, end]范围内的所有needleValue,每个section都会记录当前处于该段的所有needleValue数量,并且有一个固定的容量限制,目前版本的限制是100000,如果该段已经存储的needleValue已经达到了最大容量,但是如果要插入的key在当前[start,end]范围,那么needleValue保存到map里,也就是说values数组最大长度为100000。因为当前使用二分搜索,查找key对应的needleValue, 所以数组还是不能太大,同时使用map也能够快速的定位。
上面简单介绍了compactSection的结构,先不管怎么向某个section插入一个needleValue, 我们只用知道一个compactSection保存从[start,end]范围内的所有needleValue。所以CompactMap的list就是将key分成