SeaweedFS索引文件内存管理

当使用SeaweedFS系统储存1亿条索引数据时就会出现内存相对较大的问题,自己产生索引的key值时。

索引文件形式

索引文件中每个索引形式如下:

Key|Offset|Size

PS:Key的类型是uint64,Offset的类型是uint32,Size的类型是uint32。即索引大小为16个字节。

所以当索引数量等于1亿时,如果将索引文件直接加载到内存中,其大小约为1.5G左右。由于直接加载到内存的话,不利于索引的查找,因此必须要对索引内存进行管理。SeaweedFS提供了4中索引内存管理方式,如下:

  1. InMemory
  2. LevelDb
  3. BoltDb
  4. Btree

下面将分别对这四种内存管理方式进行讨论:

InMemory

其内存管理方式是由一系列的紧缩节组成,主要的数据结构如下:

type CompactMap struct {              // InMemory使用的内存结构
        list []*CompactSection            // 多个节组成
 }
 type CompactSection struct {        // 每个节的构成
         sync.RWMutex                      // 节对应的读写锁
         values []NeedleValue            //  节的存储空间 
         overflow map[Key]NeedleValue  // 当values存满或者key小于values最后一个key值时存放在这里
         start Key                                // 本节中最小的那个key
         end Key                                 // 本节中最大的那个key
         counter int                             // values中key值个数 
 }

InMemory时,索引插入操作如下:

  1. 首先查找是否存在能够包含当前key值的节,找到,则转2操作;未找到,则转3操作。
  2. 找到对应的节,则按key值大小顺序插入节内,如果节末key大于将要插入数据的key值或者节的大小超过bitch(默认节大小:100000),则转4操作;否则转5操作。
  3. 申请新节,并且节与节之间按照start字段的大小排序,然后转2操作继续进行插入节数据操作。
  4. 将数据存放在节中的overflow结构中。
  5. 将数据存放在values的末尾,并将counter+1

PS:

  1. 这种管理方式要求节与节有序,并且每个节之内的所有数据也是有序的。
  2. 创建新节的条件是,未找到能够包含插入值的节。

缺点

  1. 内存占用空间较大,例如两个数据也要开辟10W个数据的使用空间。
  2. 当数据上传顺序不合理时,会造成比较严重的空间浪费。(上传数据时按照数据中key值从小到大依次上传)
  3. 没有利用数据之间的关系,进行数据压缩来减少内存的占用率。

数据实测:

1G左右的索引数据,使用InMemory内存管理方式加载到内存后,内存占用大小约为3.6G左右。

BTree

SeaweedFS使用Google的度为32的BTree来实现内存索引管理,其对应的item为NeedValue。

经过实地测试,使用这种索引方式来管理内存时,1亿个索引存放在内存中的大小为5G左右。

缺点:

  1. 内存占用明显过大。

levelDb

SeaweedFS中使用的是syndtr按照google的leveldb(K/V)数据库编写的GOlang版本。

SeaweedFS中会根据索引文件的时间戳来决定是否更新levelDB对应的文件,如果启动时不存在levelDB所需要的文件,则SeaWeedFs会读取索引文件中的条目来自动生成levelDB文件。

leveldb数据库采用Snappy compression library来压缩数据,从而使数据方便存储。

数据实测:

1亿条索引,所占的内存空间为27M,申请的虚拟内存为900多M。比较符合项目要求。

PS:
SeaweedFS会在加载时统计需要删除的旧数据的大小。在使用leveldb内存管理时,会创建BTree来进行统计。
统计完成后,BTree应当被GC。但是SeaWeedFS中BTree仍然存在,没有被销毁,占用较大内存。这里需要注意!!!
sweedfs存在问题,unmout某个vid后,再mout时会出现leveldb不可用的错误。修改方案在unmout时,调用volume的close方法。

Boltdb

SeaweedFS使用的是bolt(K/V)数据。其加载以及使用方式基本与leveldb数据库相同。注意事项也一致。

你可能感兴趣的:(SeaweedFS索引文件内存管理)