Java:在内存中存储大数据(> 2GB)的官方方法是啥?

Posted

技术标签:

【中文标题】Java:在内存中存储大数据(> 2GB)的官方方法是啥?【英文标题】:Java: what is the official way to store large data (>2GB) in memory?Java:在内存中存储大数据(> 2GB)的官方方法是什么? 【发布时间】:2018-02-10 15:13:33 【问题描述】:

众所周知,在byte[] 数组中存储数据的常用方法限制为 2^31 字节 (2GB)。

有很多 Java 错误报告和 Java 规范请求可以解决这个问题。其中一些是本世纪初的文件!

但是,我发现的所有相关条目都已关闭和/或标记为重复。与此同时,每台消费类 PC 都有足够的内存,因此这个问题变得越来越重要。

所以我问自己:

处理大量内存数据的 (Java) 官方方法是什么?例如。在 RAM 中存储 4GB

如果没有官方解决方案,社区常用的解决方案是什么?

注意:我认为将数据保存到临时文件不是解决方案。超过 100GB RAM 的服务器并不少见...

【问题讨论】:

“官方”是什么意思?你要存储什么数据?你想对存储的数据做什么? 内存中的数据很少由字节组成。大多数时候,它包含在 Java 对象中。你想达到什么目的? @UsagiMiyamoto 它有什么不同? OP 正在询问如何在主内存中存储超过 2GB 的二进制数据。 @f1sh 正如@JBNizet 提到的,数据通常不仅仅是一大块字节。即使是,它也可以被分割成小块,并且可以放入byte数组的集合中...... 只是一个想法(我自己没有尝试过),但是使用LongBuffer 怎么样?理论上你可以达到 8GB 【参考方案1】:

没有所谓的“官方”方式。我从未在官方 Java 语言规范中遇到过有关此问题的任何信息。

但一般来说,你总是可以将这么大的数组表示为数组数组,即byte[][]。在这种情况下,***数组的每个元素都将描述存储的“页面”。这将允许您在理论上存储 2^31x2^31=2^62 字节。

【讨论】:

那是一个解决方案,但真的有必要让每个再次面临这个问题的开发人员都需要重新实现逻辑吗?是否没有可用的通用代码或库来抽象底层实现并提供byte[] 类似的接口?例如。从流中读取数据、将数据保存到流中、访问某些元素? 这是一个非常广泛的问题。这取决于你想存储什么样的数据以及你想如何处理它【参考方案2】:

Java 作为通用语言,目前既没有专门的工具来处理大量内存数据,也没有任何特别的官方建议。

在使用 Java 以在单个 JVM 下使用尽可能多的内存时,您有以下选择:

正如该线程中已经提到的 - 依赖于堆内数组数组,甚至更好地依赖于这些数组的 java.nio.Buffer 包装器数组 由于 32 位索引的限制,维护一堆堆外直接java.nio.ByteBuffer 的容量。 Example。这里也必须提到memory-mapped files 使用像H2这样的进程内内存数据库,记住它自己的limitations(H2甚至可以依赖own in-memory file system) 使用像Memcached这样的进程外内存存储与对应的Java client 设置RAM disk(或使用tmpfs,或类似的东西)并像使用Java文件系统一样使用内存 ...

每种方法在读/写速度、占用空间、持久性、可维护性等方面都有自己的缺点和优点。同时它取决于存储在内存中的对象的性质、它们的生命周期、访问方案、等等。

因此,必须通过严格匹配特定要求/用例来详细说明所需的选择。

【讨论】:

【参考方案3】:

由于 Andremoniy 和 Kostiantyn 现有的好答案不是我想的那样,所以我对该主题进行了更深入的调查。

我最初想到的是一个 Java 类的库或代码 sn-p,它在内部处理所有魔法(例如,将数据分块到多个字节数组)。但是由于一些愚蠢的规则,要求图书馆推荐的问题立即关闭,我无法在我的问题中写出来。

这是我发现的关于现有解决方案的集合:

fastutil: BigArrays

包名:it.unimi.dsi.fastutil 许可证:Apache commons BigArrays JavaDoc

提供具有 64 位索引的一维数组。它使用多个byte[] 在内部存储数据。它似乎是为了存储大型数字数组而开发的,因为它提供了对数组中的值进行排序的方法。

否定:访问BigArrays 似乎有点复杂,因为没有适应InputStreamOutputStream

elasticsearch BigArray

elsasticsearch 项目包含允许处理大字节(和其他原始)数组的类。 重要的类位于包org.elasticsearch.common.util。

缺点是这些类只能作为 elasticsearch 核心库的一部分使用,这个库非常大,而且还有很多依赖项。 然而,由于它使用 Apache 2.0 许可证,提取和重新打包必要的类似乎是一种合理的方式。

注意事项

我发现一个非常有趣的提示,Sun 计划早在 2009 年就为 Java NIO.2 提供一个名为 BigByteBuffer 的类。 2010 年甲骨文收购了 Sun,8 年后的今天,我们仍然没有 BigByteBufferbyte[] 以及 64 位索引...

【讨论】:

以上是关于Java:在内存中存储大数据(> 2GB)的官方方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 PostgreSQL 9.2.1 可以存储大于 2GB 的大对象?

在 c++ 程序中有效使用 POSIX 共享内存

Java应用程序消耗越来越多的内存,有时高达2GB,

读取大文件(> 2GB)(文本文件包含以太网数据)并通过不同参数随机访问数据的最佳方法是啥?

无法在 Python 中使用 Pandas 或 Blaze 加载大文件(~2gb)

请问内存有哪几种?