即使分配了8GB空间,Hazelcast最终也会出现堆空间不足的内存错误

时间:2020-06-10 08:03:56

标签: java hazelcast

在我的项目中,我需要将900万个数据从oracle数据库缓存到Hazelcast。但显然Hazelcast消耗的堆空间比预期的要多。我已为该应用程序分配了8bg堆空间,但仍然出现内存不足错误。

下面是我的数据加载器类。

 @Query("SELECT b.id FROM CustomerProfile b ")
    Iterable<Long> findAllId();

下面是存储库查询。如果我更改以下查询,使其限制为只能说200万个数据,则一切正常。

hazelcast.xml

以下是我在backup count文件中的地图配置。在这里,我以zero的形式将<?xml version="1.0" encoding="UTF-8"?> <hazelcast xsi:schemaLocation="http://www.hazelcast.com/schema/config http://www.hazelcast.com/schema/config/hazelcast-config-3.11.xsd" xmlns="http://www.hazelcast.com/schema/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <!-- Use port 5701 and upwards on this machine one for cluster members --> <network> <port auto-increment="true">5701</port> <join> <multicast enabled="false"/> <tcp-ip enabled="true"> <interface>127.0.0.1</interface> </tcp-ip> </join> </network> <map name="com.sample.hazelcast.domain.CustomerProfile"> <indexes> <!-- custom attribute without an extraction parameter --> <index ordered="false">postalCode</index> </indexes> <backup-count>0</backup-count> <map-store enabled="true" initial-mode="EAGER"> <class-name>com.sample.hazelcast.CustomerProfileLoader</class-name> </map-store> </map> </hazelcast> 设为ID NOT NULL NUMBER(19) LOGIN_ID NOT NULL VARCHAR2(32 CHAR) FIRSTNAME VARCHAR2(50 CHAR) LASTNAME VARCHAR2(50 CHAR) ADDRESS_LINE1 VARCHAR2(50 CHAR) ADDRESS_LINE2 VARCHAR2(50 CHAR) CITY VARCHAR2(30 CHAR) postal_code VARCHAR2(20 CHAR) COUNTRY VARCHAR2(30 CHAR) CREATION_DATE NOT NULL DATE UPDATED_DATE NOT NULL DATE REGISTER_NUM NOT NULL VARCHAR2(10 CHAR) ,但这没什么区别。

JAVA_OPTS=-Xmx8192m

数据库表结构:

// constrain to a discrete range
var calendar = new Calendar(calendarEl, {
  defaultView: 'dayGridMonth',
  validRange: {
    start: '2017-05-01',
    end: '2017-06-01'
  }
});

// constrain to an open-ended range
var calendar = new Calendar(calendarEl, {
  defaultView: 'dayGridMonth',
  validRange: {
    start: '2017-05-01'
  }
});

其他要点:

  • 我现在仅运行一个hazelcast服务器实例, 分配的堆空间为8GB {{1}}。之前是4GB 但是当我遇到堆空间错误时,我增加到了8GB,但是没有运气。
  • 暂时,当访问地图时会执行maploader 第一次。
  • 特定表(customer_profile)中有6列 没有任何二进制类型。它只有像 名的姓。
  • 使用的hazelcast版本是3.8

我现在面临的问题是:

获取所有数据并将其加载到映射时,出现堆空间错误( java.lang.OutOfMemoryError:Java堆空间)。现在表格中有900万个数据。

加载数据也要花费大量时间,也许我可以通过运行多个hazelcast服务器实例来解决此问题。

我是hazelcast中的新手,因此,我们将不胜感激:)

1 个答案:

答案 0 :(得分:6)

在我看来,真正的问题是8GB堆中的数据太多了。

您说您平均每行有100个字节的数据表示为字符串数据。

以下是将9,000,000行数据表示为HashMap所需空间的一些估计值 1 。假设有9个字符串,2个日期和一个int

  • 在64位JVM中,字符串的开销为48个字节+每个字符2个字节。因此,代表约100个字节字符数据的9个Java字符串总计约为650个字节。
  • Date是32字节x 2-> 64字节
  • 代表9个字符串,2个日期和1个int的记录将为112个字节。
  • 密钥(例如Integer)将是24个字节。
  • HashMap条目将为40个字节。
  • (650 + 64 + 112 + 24 + 40)x 9,000,000->〜8,000,000,000字节
  • HashMap的主数组将是2 ^ 24 x 8字节==〜128,000,000字节

您可以做到的是,实际数据超过8GB。然后考虑一下Java堆需要大量工作空间这一事实。至少说30%。

获得OOME并不奇怪。我的猜测是您的堆需要大50%...并且假设您估计的每行100字节是准确的。


这完全基于您的loadAll方法,该方法似乎正在将数据库中的所有行作为常规的HashMap来实现。它并没有考虑到Hazelcast用于缓存的堆空间或其他内存。

虽然您可以扩展堆,但是我认为更改代码以使其不会实现这样的行更有意义。目前尚不清楚这是否有意义。这将取决于地图的使用方式。


1-我假设您使用的是Java 8。