当前位置: 首页 > 工具软件 > MapDB > 使用案例 >

MapDB

鄂坚
2023-12-01

MapDB

MapDB提供了并发的Maps,Sets 和 Queues,基于磁盘存储或off-heap-memory。这是一个快速,可扩展的和易于使用的嵌入式Java数据库引擎。小但功能强大,如事务,空间高效的序列化,实例缓存和透明压缩/加密。

介绍

maven

<dependency>
    <groupId>org.mapdb</groupId>
    <artifactId>mapdb</artifactId>
    <version>VERSION</version>
</dependency>

Version 可以从这里找到http://mvnrepository.com/artifact/org.mapdb/mapdb

Simple

in-memory 方式, 使用off-heap存储,不受GC限制:

//import org.mapdb.*
DB db = DBMaker.memoryDB().make();
ConcurrentMap map = db.hashMap("map").make();
map.put("something", "here");

当关闭db object,通过指定文件存储:

DB db = DBMaker.fileDB("file.db").make();
ConcurrentMap map = db.hashMap("map").make();
map.put("something", "here");
db.close();

MapDB默认使用通用序列化方式进行序列化各种数据类型,指定特定的序列化数据类型将会更加快速与内存使用更有效率。

DB db = DBMaker
        .fileDB("file.db")
        //TODO memory mapped files enable here
        .make();
ConcurrentMap<String,Long> map = db
        .hashMap("map", Serializer.STRING, Serializer.LONG)
        .make();
map.put("something", 111L);
db.close();

HTreeMap

HTreeMap提供HashMap and HashSet集合特性,支持entry expiration,可以用作缓存。

  • 它是线程同步的,通过使用多个segments区分ReadWriteLock,支持并行写。与ConcurrentHashMap类似。segments数量可以进行配置。
  • HTreeMap是segmented Hash Tree结构。HTreeMap并不像其他HashMap,它并不会使用固定大小的Hash Table,也不会当Hash Table数据增长的时候rehash所有数据。HTreeMap使用的是auto-expanding Index Tree,因此它从不需要进行resize。不过树形结构需要更多的搜索次数,因此随机访问速度会慢些。
  • HTreeMap提供四种entry expiration标准:maximal map size(map最多元素数量), maximal storage size(最大存储量), time-to-live since last modification(最近修改存活时间) and time-to-live since last access(最近访问存活时间).Expired entries会被自动移除,使用的是FIFO queue。

创建方式

HTreeMap<String, Long> map = db.hashMap("name_of_map")
        .keySerializer(Serializer.STRING)
        .valueSerializer(Serializer.LONG)
        .create();
//or shorter form
HTreeMap<String, Long> map2 = db
        .hashMap("some_other_map", Serializer.STRING, Serializer.LONG)
        .create();

HTreeMap推荐用于处理large key/values,有时候你需要进行压缩,它能提供开启压缩store-wide,但这样仍会有瓶颈。此外,更好的方式是通过特定的serializer压缩key和value,如下:

HTreeMap<Long, String> map = db.hashMap("map")
        .valueSerializer(
                new SerializerCompressionWrapper(Serializer.STRING))
        .create();

还有Hash Code ,Layout, Expiration Overflow等定制内容,详情可以参考官网。

BTreeMap

BTreeMap提供TreeMap and TreeSet特征。它基于 lock-free concurrent B-Linked-Tree实现方式,提供small keys更好的性能,与更好的水平伸缩。

Parameters

1. serializers

使用指定的serializers将带来更好的性能,如下:

BTreeMap<Long, String> map = db.treeMap("map")
        .keySerializer(Serializer.LONG)
        .valueSerializer(Serializer.STRING)
        .createOrOpen();

2. size counter

默认情况下BTreeMap并不会跟踪map的size,通过调用map.size()去线性搜索计算所有的元素实体。如果开启了size counter,调用map.size()将马上返回,但是对insert有性能损耗。如下:

BTreeMap<Long, String> map = db
        .treeMap("map", Serializer.LONG, Serializer.STRING)
        .counterEnable()
        .createOrOpen();

3. node size

BTrees存储keys与values作为btree节点部分。节点的长度对性能的影响很大。A large node意味着许多keys在查询需要被进行反序列化。A smaller node加载会快些,但会使得BTrees层级更深和需要更多的操作。默认最大的node size是32,可以通过以下方式进行修改:

BTreeMap<Long, String> map = db
        .treeMap("map", Serializer.LONG, Serializer.STRING)
        .maxNodeSize(64)
        .createOrOpen();

Values存储作为btree叶节点部分。Large values意味着巨大的开销在单个map中。如果get(“key”)需要进行序列化,但是只返回一个值,更好的方式是存储在叶节点外,在一条单独的记录。在这种情况下,叶节点仅用6字节指向这个值。Large values可以通过压缩来减少存储空间。存储node outside BTree leaf nodes 和压缩每个值的例子:

BTreeMap<Long, String> map = db.treeMap("map")
        //TODO external values are not supported yet
        //.valuesOutsideNodesEnable()
        .valueSerializer(new SerializerCompressionWrapper(Serializer.STRING))
        .createOrOpen();

BTreeMap 需要以某种方法排序它的keys,默认情况下,大多数的Java类依靠Comparable接口的实现。如果此接口没有被实现,一个key serializer必须被提供。以下是可以比较 Object arrays 的例子:

BTreeMap<Object[], Long> map = db.treeMap("map")
        // use array serializer for unknown objects
        // TODO db.getDefaultSerializer()
        .keySerializer(new SerializerArray(Serializer.JAVA))
        // or use serializer for specific objects such as String
        .keySerializer(new SerializerArray(Serializer.STRING))
        .createOrOpen();

同样primitive arrays能被用作keys,一个String能被byte[]替代,这样将会有更好的性能:

BTreeMap<byte[], Long> map = db.treeMap("map")
        .keySerializer(Serializer.BYTE_ARRAY)
        .valueSerializer(Serializer.LONG)
        .createOrOpen();

mark 这里还有性能的测试:
http://www.mapdb.org/benchmarks/

 类似资料:

相关阅读

相关文章

相关问答