日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

mapdb java_MapDB使用入门

發布時間:2025/3/12 编程问答 58 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mapdb java_MapDB使用入门 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

背景

MapDB官網:http://www.mapdb.org

官方翻譯之后的話:MapDB基于堆外存儲、磁盤存儲提供了Java的Maps、Sets、Lists、Queues等功能。它混合了Java集合框架和數據庫引擎。它是基于Apache許可的免費的、開源的。

個人覺得:MapDB是一個輕量級的本地緩存的框架,它既可以使用對外存儲,也可以使用磁盤存儲(重啟時數據不丟失)。它還提供事務的功能。

開發文檔:https://jankotek.gitbooks.io/mapdb/content/quick-start/

開發機器配置:i5-9400 6c6t,32g內存,固態硬盤

MapDB入門實戰

1、引入jar包

org.mapdb

mapdb

3.0.7

2、基于堆外存儲的Hello,Simple

/*** 堆外內存map*/

public static voidoffHeapMapTest1() {

DB db=DBMaker.memoryDB().make();

ConcurrentMap map= db.hashMap("map").createOrOpen();

String key= "Hello";

String val= "simple";

map.put(key, val);

System.out.println("第1次取值," +map.get(key));

}

執行結果:

--Hello,simple----

第1次取值,simple

2.1、插曲

剛開始執行的時候,總是報下面的異常

Exception in thread "main" java.lang.NoClassDefFoundError: org/eclipse/collections/impl/list/mutable/primitive/LongArrayList

at org.mapdb.StoreDirectAbstract.(StoreDirectAbstract.kt:41)

at org.mapdb.StoreDirect.(StoreDirect.kt:30)

at org.mapdb.StoreDirect$Companion.make(StoreDirect.kt:57)

at org.mapdb.StoreDirect$Companion.make$default(StoreDirect.kt:56)

at org.mapdb.DBMaker$Maker.make(DBMaker.kt:450)

at me.lovegao.mapdb.hello.HelloWorldDemo.offHeapMapTest1(HelloWorldDemo.java:18)

at me.lovegao.mapdb.hello.HelloWorldDemo.main(HelloWorldDemo.java:11)

Caused by: java.lang.ClassNotFoundException: org.eclipse.collections.impl.list.mutable.primitive.LongArrayList

at java.net.URLClassLoader.findClass(URLClassLoader.java:381)

at java.lang.ClassLoader.loadClass(ClassLoader.java:424)

at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)

at java.lang.ClassLoader.loadClass(ClassLoader.java:357)

... 7 more

我以為是jar包沒加全,又加了Eclipse相關的jar包,發現還是這樣。對著項目又是清理,又是重新編譯,又是重新導包,發現都不行。

仔細看了maven的依賴,都是存在的,看MapDB的文檔,也說上面那個配置包含全部的。

最后,索性把本地相關的jar包都刪了,讓maven重新下,最終正常了。

3、基于磁盤的Hello,Simple

基于磁盤存儲的,為了保證數據的完整性,需要在關閉虛擬機前關閉DB。

public static voidfileMapTest1() {

DB db= DBMaker.fileDB("file.db").make();

ConcurrentMap map= db.hashMap("map").createOrOpen();

String key= "something";

String val= "here";

map.put(key, val);

System.out.println("第1次取值," +map.get(key));

db.close();

System.out.println("----------重新打開----------");

db= DBMaker.fileDB("file.db").make();

map= db.hashMap("map").createOrOpen();

System.out.println("第2次取值," +map.get(key));

db.close();

}

執行結果:

--Hello,simple----

第1次取值,simple

----------重新打開----------

第2次取值,simple

結果符合預期。

3.1、基于磁盤的,內存映射的使用

/*** 在64位操作系統中,開啟內存映射

* 個性化序列化*/

public static voidfileMapMemoryMapTest() {

DB db=DBMaker

.fileDB("file.db")

.fileMmapEnable()

.make();

ConcurrentMap map =db

.hashMap("mapsl", Serializer.STRING, Serializer.LONG)

.createOrOpen();long val = 51;

map.put(DEMO_KEY, val);

System.out.println("第1次取值,期望值:" + val + ",取到的值:" +map.get(DEMO_KEY));

db.close();

db=DBMaker

.fileDB("file.db")

.fileMmapEnable()

.make();

map= db.hashMap("mapsl", Serializer.STRING, Serializer.LONG)

.createOrOpen();

System.out.println("第2次取值,期望值:" + val + ",取到的值:" +map.get(DEMO_KEY));

db.close();

}

執行結果:

--Hello,simple----

第1次取值,期望值:51,取到的值:51

第2次取值,期望值:51,取到的值:51

4、性能對比

1)測試代碼

packageme.lovegao.mapdb.hello;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.Iterator;importjava.util.List;importjava.util.Map;importjava.util.Map.Entry;importjava.util.concurrent.ConcurrentMap;importorg.eclipse.collections.impl.map.mutable.ConcurrentHashMap;importorg.mapdb.DB;importorg.mapdb.DBMaker;importorg.mapdb.Serializer;public classMapDBSpeedTest {private final static String DEMO_KEY = "Hello";private final static String DEMO_VAL = "simple";public static voidmain(String[] args) {

System.out.println("--Hello,simple----");//fileMapMemoryMapTest();

mapTest();

}public static voidmapTest() {int dataNum = 10000;

List dbList = newArrayList();

Map> testMap = newHashMap();

Map dataMap =generateTestData(dataNum);//java原生-堆內map

ConcurrentMap inHeapDbMap = newConcurrentHashMap();

testMap.put("原生map", inHeapDbMap);//堆外map

DB offHeapDb =DBMaker.memoryDB().make();

dbList.add(offHeapDb);

ConcurrentMap offHeapDbMap= offHeapDb.hashMap("map").createOrOpen();

testMap.put("堆外map", offHeapDbMap);//基于磁盤map

DB fileDb = DBMaker.fileDB("file1.db").make();

dbList.add(fileDb);

ConcurrentMap fileDbMap =fileDb

.hashMap("map1", Serializer.STRING, Serializer.LONG)

.createOrOpen();

testMap.put("基于磁盤map", fileDbMap);//基于磁盤-內存映射map

DB fileMmapDb =DBMaker

.fileDB("file2.db")

.fileChannelEnable()//By default MapDB uses RandomAccessFile to access disk storage. Outside fast mmap files there is third option based on FileChannel. It should be faster than RandomAccessFile

.fileMmapEnable() //Always enable mmap//.fileMmapEnableIfSupported()//Only enable mmap on supported platforms,對性能影響較大

.fileMmapPreclearDisable() //Make mmap file faster//.allocateStartSize( 10 * 1024*1024*1024)//10GB,初始容量//.allocateIncrement(512 * 1024*1024)//512MB,每次增加容量

.make();//optionally preload file content into disk cache

fileMmapDb.getStore().fileLoad();

dbList.add(fileMmapDb);

ConcurrentMap fileMmapMap =fileMmapDb

.hashMap("map2", Serializer.STRING, Serializer.LONG)

.createOrOpen();

testMap.put("基于磁盤-內存映射map", fileMmapMap);

System.out.println("-----------put---數據量:"+dataNum+"------");for(String mapType : testMap.keySet()) {

putGetMapTest(mapType, testMap.get(mapType), dataMap,true);

}

System.out.println("-----------------------------------------\n");

System.out.println("-----------get---數據量:"+dataNum+"------");for(String mapType : testMap.keySet()) {

putGetMapTest(mapType, testMap.get(mapType), dataMap,false);

}for(DB db : dbList) {

db.close();

}

}/*** putGet測試

*@parammap

*@paramdataMap

*@paramput

*@return*/

public static TwoTuple putGetMapTest(String mapType, Map map, Map dataMap, booleanput) {long useTime = 0L;long errorNum = 0L;

Iterator> entryIt =dataMap.entrySet().iterator();while(entryIt.hasNext()) {

Entry entry =entryIt.next();if(put) {long t1 =System.nanoTime();

map.put(entry.getKey(), entry.getValue());

useTime= System.nanoTime() -t1;

}else{long t1 =System.nanoTime();long val =map.get(entry.getKey());

useTime= System.nanoTime() -t1;if(val !=entry.getValue()) {

errorNum++;

}

}

}double avgUseTime = (double)useTime /dataMap.size();

String fmtStr= "map類型:%s,總耗時:%dns,平均耗時%ens,異常數量:%d";

System.out.println(String.format(fmtStr, mapType, useTime, avgUseTime, errorNum));return new TwoTuple(useTime, errorNum);

}/*** 生成測試數據

*@paramsize

*@return

*/

public static Map generateTestData(intsize) {

Map map = newHashMap();int arrLength = 26;char[] words = new char[arrLength];for(int i=0; i

words[i]= (char) ('a' +i);

}

System.out.println(words);

String demoWord= newString(words);for(int i=0; i

String key= demoWord.substring(i%arrLength, i%arrLength) +i;long val =i;

map.put(key, val);

}returnmap;

}/*** 對外內存map*/

public static voidoffHeapMapTest1() {

DB db=DBMaker.memoryDB().make();

ConcurrentMap map= db.hashMap("map").createOrOpen();

map.put(DEMO_KEY, DEMO_VAL);

System.out.println("第1次取值," +map.get(DEMO_KEY));

}/*** 基于磁盤的存儲*/

public static voidfileMapTest1() {

DB db= DBMaker.fileDB("file.db").make();

ConcurrentMap map= db.hashMap("map").createOrOpen();

map.put(DEMO_KEY, DEMO_VAL);

System.out.println("第1次取值," +map.get(DEMO_KEY));

db.close();

System.out.println("----------重新打開----------");

db= DBMaker.fileDB("file.db").make();

map= db.hashMap("map").createOrOpen();

System.out.println("第2次取值," +map.get(DEMO_KEY));

db.close();

}/*** 在64位操作系統中,開啟內存映射

* 個性化序列化*/

public static voidfileMapMemoryMapTest() {

DB db=DBMaker

.fileDB("file.db")

.fileMmapEnable()

.make();

ConcurrentMap map =db

.hashMap("mapsl", Serializer.STRING, Serializer.LONG)

.createOrOpen();long val = 51;

map.put(DEMO_KEY, val);

System.out.println("第1次取值,期望值:" + val + ",取到的值:" +map.get(DEMO_KEY));

db.close();

db=DBMaker

.fileDB("file.db")

.fileMmapEnable()

.make();

map= db.hashMap("mapsl", Serializer.STRING, Serializer.LONG)

.createOrOpen();

System.out.println("第2次取值,期望值:" + val + ",取到的值:" +map.get(DEMO_KEY));

db.close();

}

}

2)測試結果

map類型

測試數據量

測試類型

總耗時(ns)

平均耗時(ns)

原生map

10000

put

100

1.000000e-02

堆外map

同上

put

4800

4.800000e-01

基于磁盤map

同上

put

345000

3.450000e+01

基于磁盤-內存映射map

同上

put

6000

6.000000e-01

原生map

同上

get

100

1.000000e-02

堆外map

同上

get

2000

2.000000e-01

基于磁盤map

同上

get

75400

7.540000e+00

基于磁盤-內存映射map

同上

get

1100

1.100000e-01

3)結論

①原生的基于堆的map速度始終是最快的

②堆外map和基于磁盤且開啟了內存映射的map相比,優勢較小。至于原因,有待深入理解。

③對于“基于磁盤-內存映射map”,使用“fileMmapEnableIfSupported”配置,對性能影響較大,建議直接開啟。配置“fileMmapPreclearDisable”對于put的性能提升較大(約一倍提升)。

MapDB事務

MapDB是支持事務的,具體使用如下:

packageme.lovegao.mapdb.hello;importjava.util.concurrent.ConcurrentMap;importorg.mapdb.DB;importorg.mapdb.DBMaker;importorg.mapdb.Serializer;public classMapDBTransaction {public static voidmain(String[] args) {

DB db=DBMaker

.fileDB("file3.db")

.fileMmapEnable()

.transactionEnable()

.closeOnJvmShutdown() //JVM關閉時關閉db

.make();

ConcurrentMap map =db

.hashMap("mapsl3", Serializer.STRING, Serializer.LONG)

.createOrOpen();

map.put("a", 1L);

map.put("b", 2L);

db.commit();

System.out.println(map.get("a"));

System.out.println(map.get("b"));

map.put("c", 3L);

System.out.println("rollback之前,c:" + map.get("c"));

db.rollback();

System.out.println("rollback之后,a:" + map.get("a"));

System.out.println("rollback之后,c:" + map.get("c"));

}

}

運行結果:

1

2

rollback之前,c:3

rollback之后,a:1

rollback之后,c:null

因為配置了closeOnJvmShutdown,所以再次運行時能夠正常運行。

如果去掉了transactionEnable和closeOnJvmShutdown,再次運行時將出現以下異常:

Exception in thread "main" org.mapdb.DBException$DataCorruption: Header checksum broken. Store was not closed correctly and might be corrupted. Use `DBMaker.checksumHeaderBypass()` to recover your data. Use clean shutdown or enable transactions to protect the store in the future.

at org.mapdb.StoreDirectAbstract.fileHeaderCheck(StoreDirectAbstract.kt:113)

at org.mapdb.StoreDirect.(StoreDirect.kt:114)

at org.mapdb.StoreDirect$Companion.make(StoreDirect.kt:57)

at org.mapdb.StoreDirect$Companion.make$default(StoreDirect.kt:56)

at org.mapdb.DBMaker$Maker.make(DBMaker.kt:450)

at me.lovegao.mapdb.hello.MapDBTransaction.main(MapDBTransaction.java:17)

最后說以下,fileDB("file3.db")這里的路徑可以指定其他目錄,默認是在項目的根目錄下。

路徑是自己創建的,文件是MapDB自動創建的,切記不要多此一舉,把文件也創建了,那樣會報錯的。

總結

以上是生活随笔為你收集整理的mapdb java_MapDB使用入门的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。