我在分布式缓存中保留了很多小对象。大多数操作都是本地的,意味着他们在同一个节点访问数据(我正在使用分区感知功能)。即使数据位于同一节点,Hazelcast仍然需要反序列化消耗大量内存的项目,并使应用程序因 OutOfMemoryError 而崩溃以获得更多顶点,并且对它们并行执行更多操作。我知道有一个 near-cache ,我可以使用 cache-local-entries 和 data-format 等于 OBJECT 但这不合适,因为我对这些数据做了一些变异操作。我还使用 IdentifiedDataSerializable 来存储数据和所有被序列化的东西,所以无法从那里获得任何东西。
这是示例OOM错误堆栈跟踪(它在节点端抛出,而不是在客户端抛出):
java.lang.OutOfMemoryError: Java heap space
at com.hazelcast.internal.serialization.impl.ByteArrayObjectDataOutput.ensureAvailable(ByteArrayObjectDataOutput.java:359)
at com.hazelcast.internal.serialization.impl.ByteArrayObjectDataOutput.write(ByteArrayObjectDataOutput.java:70)
at java.io.OutputStream.write(OutputStream.java:75)
at com.hazelcast.internal.serialization.impl.ByteArrayObjectDataOutput.writeByteArray(ByteArrayObjectDataOutput.java:263)
at com.hazelcast.internal.serialization.impl.ByteArrayObjectDataOutput.writeData(ByteArrayObjectDataOutput.java:376)
at com.hazelcast.map.impl.MapEntries.writeData(MapEntries.java:141)
at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.write(DataSerializableSerializer.java:197)
at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.write(DataSerializableSerializer.java:49)
at com.hazelcast.internal.serialization.impl.StreamSerializerAdapter.write(StreamSerializerAdapter.java:43)
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.writeObject(AbstractSerializationService.java:249)
at com.hazelcast.internal.serialization.impl.ByteArrayObjectDataOutput.writeObject(ByteArrayObjectDataOutput.java:370)
at com.hazelcast.spi.impl.operationservice.impl.operations.PartitionIteratingOperation$PartitionResponse.writeData(PartitionIteratingOperation.java:289)
at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.write(DataSerializableSerializer.java:197)
at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.write(DataSerializableSerializer.java:49)
at com.hazelcast.internal.serialization.impl.StreamSerializerAdapter.write(StreamSerializerAdapter.java:43)
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.writeObject(AbstractSerializationService.java:249)
at com.hazelcast.internal.serialization.impl.ByteArrayObjectDataOutput.writeObject(ByteArrayObjectDataOutput.java:370)
at com.hazelcast.spi.impl.operationservice.impl.responses.NormalResponse.writeData(NormalResponse.java:91)
at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.write(DataSerializableSerializer.java:197)
at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.write(DataSerializableSerializer.java:49)
at com.hazelcast.internal.serialization.impl.StreamSerializerAdapter.write(StreamSerializerAdapter.java:43)
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.toBytes(AbstractSerializationService.java:151)
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.toBytes(AbstractSerializationService.java:125)
at com.hazelcast.spi.impl.operationservice.impl.OutboundResponseHandler.send(OutboundResponseHandler.java:88)
at com.hazelcast.spi.impl.operationservice.impl.OutboundResponseHandler.sendResponse(OutboundResponseHandler.java:64)
at com.hazelcast.spi.Operation.sendResponse(Operation.java:338)
at com.hazelcast.spi.impl.operationservice.impl.operations.PartitionIteratingOperation$OperationResponseHandlerImpl.sendResponse(PartitionIteratingOperation.java:219)
at com.hazelcast.spi.impl.operationservice.impl.operations.PartitionIteratingOperation$OperationResponseHandlerImpl.sendResponse(PartitionIteratingOperation.java:207)
at com.hazelcast.spi.Operation.sendResponse(Operation.java:338)
at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.sendResponse(OperationRunnerImpl.java:279)
at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.handleResponse(OperationRunnerImpl.java:270)
at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.run(OperationRunnerImpl.java:187)
Jun 11, 2017 9:57:51 PM com.hazelcast.map.impl.operation.PartitionWideEntryWithPredicateOperation
SEVERE: [10.6.3.57]:5701 [kpts-cluster] [3.8] Java heap space
java.lang.OutOfMemoryError: Java heap space
at com.hazelcast.internal.serialization.impl.ByteArrayObjectDataOutput.ensureAvailable(ByteArrayObjectDataOutput.java:359)
at com.hazelcast.internal.serialization.impl.ByteArrayObjectDataOutput.write(ByteArrayObjectDataOutput.java:70)
at java.io.OutputStream.write(OutputStream.java:75)
at com.hazelcast.internal.serialization.impl.ByteArrayObjectDataOutput.writeByteArray(ByteArrayObjectDataOutput.java:263)
at com.hazelcast.internal.serialization.impl.ByteArrayObjectDataOutput.writeData(ByteArrayObjectDataOutput.java:376)
at com.hazelcast.map.impl.MapEntries.writeData(MapEntries.java:141)
at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.write(DataSerializableSerializer.java:197)
at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.write(DataSerializableSerializer.java:49)
at com.hazelcast.internal.serialization.impl.StreamSerializerAdapter.write(StreamSerializerAdapter.java:43)
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.writeObject(AbstractSerializationService.java:249)
at com.hazelcast.internal.serialization.impl.ByteArrayObjectDataOutput.writeObject(ByteArrayObjectDataOutput.java:370)
at com.hazelcast.spi.impl.operationservice.impl.operations.PartitionIteratingOperation$PartitionResponse.writeData(PartitionIteratingOperation.java:289)
at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.write(DataSerializableSerializer.java:197)
at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.write(DataSerializableSerializer.java:49)
at com.hazelcast.internal.serialization.impl.StreamSerializerAdapter.write(StreamSerializerAdapter.java:43)
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.writeObject(AbstractSerializationService.java:249)
at com.hazelcast.internal.serialization.impl.ByteArrayObjectDataOutput.writeObject(ByteArrayObjectDataOutput.java:370)
at com.hazelcast.spi.impl.operationservice.impl.responses.NormalResponse.writeData(NormalResponse.java:91)
at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.write(DataSerializableSerializer.java:197)
at com.hazelcast.internal.serialization.impl.DataSerializableSerializer.write(DataSerializableSerializer.java:49)
at com.hazelcast.internal.serialization.impl.StreamSerializerAdapter.write(StreamSerializerAdapter.java:43)
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.toBytes(AbstractSerializationService.java:151)
at com.hazelcast.internal.serialization.impl.AbstractSerializationService.toBytes(AbstractSerializationService.java:125)
at com.hazelcast.spi.impl.operationservice.impl.OutboundResponseHandler.send(OutboundResponseHandler.java:88)
at com.hazelcast.spi.impl.operationservice.impl.OutboundResponseHandler.sendResponse(OutboundResponseHandler.java:64)
at com.hazelcast.spi.Operation.sendResponse(Operation.java:338)
at com.hazelcast.spi.impl.operationservice.impl.operations.PartitionIteratingOperation$OperationResponseHandlerImpl.sendResponse(PartitionIteratingOperation.java:219)
at com.hazelcast.spi.impl.operationservice.impl.operations.PartitionIteratingOperation$OperationResponseHandlerImpl.sendResponse(PartitionIteratingOperation.java:207)
at com.hazelcast.spi.Operation.sendResponse(Operation.java:338)
at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.sendResponse(OperationRunnerImpl.java:279)
at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.handleResponse(OperationRunnerImpl.java:270)
at com.hazelcast.spi.impl.operationservice.impl.OperationRunnerImpl.run(OperationRunnerImpl.java:187)
中的样子
这是几乎崩溃的时候。任何更大的问题都会失败。
有趣的是,我要使用多少个节点并不重要。它们仍然会消耗很多内存空间,但仍然会失败。所以它不是关于存储数据而是关于检索它的能力......
还有其他方法可以使反序列化消耗更少的内存吗?
答案 0 :(得分:3)
避免反序列化开销的最佳方法是将实际数据存储在每个节点内的静态映射中,并使用Hazelcast执行器作为路由器将请求路由到包含该数据的节点。
IExecutorService.submitToKeyOwner()
将请求路由到拥有段密钥的节点,在该节点内,您可以将实际值保存在静态映射中。
请注意,在这种方法中,您需要自己清理本地静态地图。虽然您可以使用MapEvent侦听器来处理清理。