当前位置: 首页 > 后端技术 > Java

H2存储内核分析

时间:2023-04-01 13:38:48 Java

概述MVStore是“Multi-VersionStore”的缩写,是一种基于日志结构的持久化key-value存储。它是H2默认的存储引擎,支持SQL、JDBC、事务、MVCC等。但也可以不使用JDBC或SQL,直接在应用中使用。以下是MVStore的特点:内部包含多个Map,可以使用Java中的java.util.Map接口访问。支持基于文件的持久化和内存操作,旨在快速、易于使用且体积小。支持并发读写操作和事务(包括并发事务和两阶段提交)。支持插件数据类型和序列化、插件存储(文件、堆外内存)、插件Map实现(B-tree、R-tree、并发B-tree)、BLOB存储和文件系统抽象支持加密文件和zip文件。示例StringfileName="/Users/chenfei/temp/my_store.db";FileUtils.delete(文件名);MVStore.Builder构建器=newMVStore.Builder();builder.fileName(文件名);builder.pageSplitSize(1000);MVStorestore=builder.open();MVMapm=store.openMap("data");整数计数=2;for(inti=0;imetaMap=store.getMetaMap();在readStoreHeader方法中获取第一个chunkreadChunkHeaderAndFooter(block);将通过setLastChunk方法设置块。/***获取最新的块*/publicChunksetLastChunk(Chunklast){chunks.clear();最后一个块=最后一个;if(last==null){//没有有效的块lastMapId.set(0);当前版本=0;lastStoredVersion=MVMap.INITIAL_VERSION;meta.setRootPos(0,MVMap.INITIAL_VERSION);}else{lastMapId.set(last.mapId);当前版本=最后一个版本;chunks.put(last.id,last);lastStoredVersion=currentVersion-1;meta.setRootPos(last.metaRootPos,lastStoredVersion);最后返回;}获取块的根页面Stringname="my_data_1";MVMap.MapBuildermapBuilder=newMVMap.Builder();intid=store.getMapId(名称);MVMapmap=store.getMap(id);if(map==null){StringconfigAsString=store.getMetaMap().get(MVMap.getMapKey(id));HashMap<字符串,O对象>配置;if(configAsString!=null){config=newHashMap(DataUtils.parseMap(configAsString));}else{config=newHashMap<>();}config.put("id",id);map=mapBuilder.create(store,config);longroot=store.getRootPos(store.getMetaMap(),id);//该方法是从文件中提取页面map.setRootPos(root,MVMap.INITIAL_VERSION);store.maps.put(id,地图);//提取页面Pagep=map.getRootPage();System.out.println(p);}Page类是核心类,用于操作数据输入Page和要查询的索引,查询结果通过tree/***获取给定key的值,找不到则为null。*搜索是在以给定页面为根的树中完成的。**@paramkey键*@paramp根页面*@return值,如果找不到则返回null*/publicstaticObjectget(Pagep,Objectkey){while(true){intindex=p.binarySearch(key);如果(p.isLeaf()){返回索引>=0?p.getValue(索引):空;}elseif(index++<0){index=-index;}p=p.getChildPage(index);}}向叶节点插入键值publicvoidinsertLeaf(intindex,Objectkey,Objectvalue){intkeyCount=getKeyCount();插入键(索引,键);如果(值!=null){对象[]newValues=createValueStorage(keyCount+1);DataUtils.copyWithGap(values,newValues,keyCount,index);值=newValues;setValueInternal(索引,值);if(isPersistent()){addMemory(MEMORY_POINTER+map.getValueType().getMemory(value));}}}至此,读者基本了解了h2的存储核心,比较简单,易于掌握和扩展如果你对存储内核感兴趣,可以加入DawnSql交流群,告诉我,我会继续写。DawnSql交流群,可以在https://docs.dawnsql.com/首页查看(打开有点慢,稍等)说明一点:有朋友有疑问,为什么DawnSql选择存储h2的核心而不是去做一个新的?这主要是为了高可用性!h2作为一个成熟的数据库存储内核,已经在实际项目中使用多年,经得起考验。如果构建新的存储内核,可能会给用户带来高可用的顾虑,所以我们慎重考虑后选择更稳定、高可用的方案。当然,随着DawnSql的发展,根据企业的要求,我们也可以对其进行修改和重构!