/ codeserf / Java非托管堆存储数据

Java非托管堆存储数据

2013-02-22 posted in [编程语言]

当前随着Nosql的兴起,已经有大量的key-value存储或者缓存的系统,基本没必要重复造轮子,但是对于引入例如redis/memcached这样的系统,则必须使用其协议,不能重用现有的一套东西,所以想着开发一套Java的缓存系统。

一般的方案是通过HashMap这样的结构保存数据, 但是这样一般有两个问题,一是太浪费内存,java对象占用的空间太大。二是随着内存使用的增大,对于GC而已负担太大。所以我实现的方案是将大部分数据保存在非托管堆上,部分索引数据保存在托管堆上。

主要的Feature如下:

主要的实现细节如下:

数据储存

记录格式如下::

+--------------+------------------+
|     name     |      length      |
+--------------+------------------+
| magic number | 1byte            |
| next         | 8byte            |
| key size     | varint           |
| value size   | varint           |
| key          | <data>           |
| value        | <data>           |
| padding      | <not used space> |
+--------------+------------------+

记录存放在在NonHeap分配的数据段,每个数据段为固定大小,可以在初始化的时候指定。

索引记录

在DB被初始化的时候可以指定hashpower,其用于定于索引buckets的大小,根据预计的缓存量进行分配,如果太小,将导致冲突链增大,将极大的影响性能。

索引buckets为long类型的数组,buckets里的值保存记录在NonHeap数据区的偏移以及整个大小。前2个字节为大小,后2个字节为数据段的index, 最后4个字节为在数据段的偏移。

碎片管理

记录被删除后,将magic number置为删除状态,并按照其size有序的保存在分配在托管堆的TreeSet里。在下次分配记录空间的时候,先通过bestfit的方式查找到最适合的大小,复用原有的空间。

在碎片率到达一定程度后,将对数据段进行碎片整理,将多个碎片合并为一个碎片。

PS: 可以使用类似memcached slab分配器的方式分配内存,这样出现碎片的机率比较小。

项目地址在https://github.com/believe3301/NonHeapDB

-EOF-

codeserfRSS feed

About

tiger yang

enjoy coding,enjoy life

Copyright

知识共享许可协议

Fork me on GitHub

Powered by

Disqus, GitHub, Google Custom Search, Gravatar, HighlightJS, jekyll