Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/380.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 用于DB实现的内存映射MappedByteBuffer还是直接ByteBuffer?_Java_File Io_Database Design_Memory Mapped Files_Bytebuffer - Fatal编程技术网

Java 用于DB实现的内存映射MappedByteBuffer还是直接ByteBuffer?

Java 用于DB实现的内存映射MappedByteBuffer还是直接ByteBuffer?,java,file-io,database-design,memory-mapped-files,bytebuffer,Java,File Io,Database Design,Memory Mapped Files,Bytebuffer,这看起来像一个很长的问题,因为所有的背景。下面这本小说有两个问题。感谢您花时间阅读本文并提供帮助 形势 我正在开发一个可扩展的数据存储实现,它可以支持在32位或64位系统上处理大小从几KB到TB或更大的数据文件 数据存储采用写时拷贝设计;始终将新的或修改的数据附加到数据文件的末尾,而从不对现有数据进行就地编辑 系统可承载1个或多个数据库;每个都由磁盘上的一个文件表示 实施的细节并不重要;唯一重要的细节是,我需要不断地追加到文件中,并将其从KB增长到MB,从GB增长到TB,同时随机跳过文件以执行读

这看起来像一个很长的问题,因为所有的背景。下面这本小说有两个问题。感谢您花时间阅读本文并提供帮助

形势

我正在开发一个可扩展的数据存储实现,它可以支持在32位或64位系统上处理大小从几KB到TB或更大的数据文件

数据存储采用写时拷贝设计;始终将新的或修改的数据附加到数据文件的末尾,而从不对现有数据进行就地编辑

系统可承载1个或多个数据库;每个都由磁盘上的一个文件表示

实施的细节并不重要;唯一重要的细节是,我需要不断地追加到文件中,并将其从KB增长到MB,从GB增长到TB,同时随机跳过文件以执行读取操作以响应客户端请求

最初的想法

乍一看,我知道我想使用内存映射文件,这样我就可以将高效管理内存中数据状态的负担推到主机操作系统上,并从代码中释放出来

然后,我的代码需要担心的就是在写入时序列化追加到文件的操作,并允许任意数量的同时读取器在文件中查找以响应请求

设计

由于单个数据文件的增长可能超过MappedByteBuffer的2GB限制,因此我希望我的设计必须包括一个抽象层,该抽象层采用写入偏移量,并将其转换为特定2GB段内的偏移量

到目前为止还不错

问题

这就是我开始挂断电话的地方,我认为采用不同的设计(建议如下)可能是更好的方法

从这里阅读20个左右的“内存映射”相关问题来看,mmap调用似乎对在分配内存时需要连续运行的内存很敏感。因此,例如,在32位主机操作系统上,如果我尝试mmap一个2GB的文件,由于内存碎片,映射成功的可能性很小,相反,我应该使用一系列类似128MB的映射来拉入整个文件

当我想到这种设计时,即使使用1024MB的mmap大小,对于一个拥有几个大型数据库的DBMS(所有数据库都由1TB的文件表示),我现在在内存中有数千个内存映射区域,在我自己在Windows 7上的测试中,试图在一个多GB的文件中创建几百个mmap,我并没有遇到异常,事实上,每次我试图分配太多的资源时,我都会让JVM出错,有一次,我让Windows 7机器中的视频被剪切,并用一个我从未见过的操作系统错误弹出窗口重新初始化

不管“你永远不可能处理大文件”或“这是一个虚构的例子”的论点,事实上,我可以用这种类型的副作用编码类似的东西,使我的内部警报处于高度警戒状态,并考虑另一个IMPL(以下)。 除此之外,我对内存映射文件的理解是,每次文件增长时,我都必须重新创建映射,因此对于仅在设计中附加的文件,它实际上是不断增长的

在某种程度上,我可以通过将文件分块增长(比如一次8MB)并只每隔8MB重新创建映射来解决这个问题,但是不断地重新创建这些映射的需要让我感到紧张,特别是在没有显式映射的情况下

问题#第1个,共2个

考虑到目前为止我的所有发现,我认为内存映射文件是主要用于读取大量解决方案或只读解决方案的良好解决方案,但由于需要不断重新创建映射,因此不会写入大量解决方案

但当我环顾四周时,我发现像MongoDB这样的解决方案到处都是内存映射文件,我觉得我缺少了一些核心组件(我确实知道它一次分配2GB的数据块,所以我想他们正在用这种逻辑解决重新映射的成本问题,并帮助在磁盘上保持顺序运行)

在这一点上,我不知道问题是Java缺少一个取消映射操作,这使得它变得非常危险,不适合我使用,还是我的理解不正确,有人可以指点我北上

替代设计

如果我对mmap的理解是正确的,我将采用上述内存映射的替代设计,如下所示:

定义一个合理的可配置大小(大约2、4、8、16、32、64、128KB),使其易于与任何主机平台兼容(无需担心DBMS本身会导致抖动场景),并使用原始FileChannel,一次执行文件1缓冲区容量块,完全放弃内存映射文件

缺点是,现在我的代码不得不担心“我是否从文件中读取了足够的内容来加载完整的记录?”

另一个不利的方面是,我不能利用操作系统的虚拟内存逻辑,让它自动在内存中保存更多的“热”数据;相反,我只希望操作系统使用的文件缓存逻辑足够大,可以在这里为我做些有帮助的事情

问题#2/2

我希望能证实我对这一切的理解

例如,文件缓存可能非常棒,在这两种情况下(内存映射或直接读取),主机操作系统将尽可能多地保留我的热数据,而大文件的性能差异可以忽略不计


或者我对内存映射文件(连续内存)敏感需求的理解不正确,我可以忽略所有这些。

我认为您不应该担心最大2GB的mmap文件

看着酸溜溜的