【问题标题】:Cassandra terminates with OutOfMemory (OOM) errorCassandra 以 OutOfMemory (OOM) 错误终止
【发布时间】:2013-06-18 21:47:24
【问题描述】:

我们在 AWS 上有一个 3 节点的 cassandra 集群。这些节点运行 cassandra 1.2.2 并具有 8GB 内存。我们没有更改任何默认堆或 GC 设置。所以每个节点都分配了 1.8GB 的​​堆空间。行很宽;每行存储大约 260,000 列。我们正在使用 Astyanax 读取数据。如果我们的应用程序尝试同时从 10 行或更多行中读取 80,000 列,则某些节点会耗尽堆空间并以 OOM 错误终止。这是错误消息:

java.lang.OutOfMemoryError: Java heap space
        at java.nio.HeapByteBuffer.duplicate(HeapByteBuffer.java:107)
        at org.apache.cassandra.db.marshal.AbstractCompositeType.getBytes(AbstractCompositeType.java:50)
        at org.apache.cassandra.db.marshal.AbstractCompositeType.getWithShortLength(AbstractCompositeType.java:60)
        at org.apache.cassandra.db.marshal.AbstractCompositeType.split(AbstractCompositeType.java:126)
        at org.apache.cassandra.db.filter.ColumnCounter$GroupByPrefix.count(ColumnCounter.java:96)
        at org.apache.cassandra.db.filter.SliceQueryFilter.collectReducedColumns(SliceQueryFilter.java:164)
        at org.apache.cassandra.db.filter.QueryFilter.collateColumns(QueryFilter.java:136)
        at org.apache.cassandra.db.filter.QueryFilter.collateOnDiskAtom(QueryFilter.java:84)
        at org.apache.cassandra.db.CollationController.collectAllData(CollationController.java:294)
        at org.apache.cassandra.db.CollationController.getTopLevelColumns(CollationController.java:65)
        at org.apache.cassandra.db.ColumnFamilyStore.getTopLevelColumns(ColumnFamilyStore.java:1363)
        at org.apache.cassandra.db.ColumnFamilyStore.getColumnFamily(ColumnFamilyStore.java:1220)
        at org.apache.cassandra.db.ColumnFamilyStore.getColumnFamily(ColumnFamilyStore.java:1132)
        at org.apache.cassandra.db.Table.getRow(Table.java:355)
        at org.apache.cassandra.db.SliceFromReadCommand.getRow(SliceFromReadCommand.java:70)
        at org.apache.cassandra.service.StorageProxy$LocalReadRunnable.runMayThrow(StorageProxy.java:1052)
        at org.apache.cassandra.service.StorageProxy$DroppableRunnable.run(StorageProxy.java:1578)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
        at java.lang.Thread.run(Thread.java:722)

ERROR 02:14:05,351 Exception in thread Thread[Thrift:6,5,main] java.lang.OutOfMemoryError: Java heap space
        at java.lang.Long.toString(Long.java:269)
        at java.lang.Long.toString(Long.java:764)
        at org.apache.cassandra.dht.Murmur3Partitioner$1.toString(Murmur3Partitioner.java:171)
        at org.apache.cassandra.service.StorageService.describeRing(StorageService.java:1068)
        at org.apache.cassandra.thrift.CassandraServer.describe_ring(CassandraServer.java:1192)
        at org.apache.cassandra.thrift.Cassandra$Processor$describe_ring.getResult(Cassandra.java:3766)
        at org.apache.cassandra.thrift.Cassandra$Processor$describe_ring.getResult(Cassandra.java:3754)
        at org.apache.thrift.ProcessFunction.process(ProcessFunction.java:32)
        at org.apache.thrift.TBaseProcessor.process(TBaseProcessor.java:34)
        at org.apache.cassandra.thrift.CustomTThreadPoolServer$WorkerProcess.run(CustomTThreadPoolServer.java:199)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
        at java.lang.Thread.run(Thread.java:722) ERROR 02:14:05,350 Exception in thread Thread[ACCEPT-/10.0.0.170,5,main] java.lang.RuntimeException: java.nio.channels.ClosedChannelException
        at org.apache.cassandra.net.MessagingService$SocketThread.run(MessagingService.java:893) Caused by: java.nio.channels.ClosedChannelException
        at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:211)
        at sun.nio.ch.ServerSocketAdaptor.accept(ServerSocketAdaptor.java:99)
        at org.apache.cassandra.net.MessagingService$SocketThread.run(MessagingService.java:882)

每列的数据小于 50 字节。添加所有列开销(列名 + 元数据)后,不应超过 100 个字节。所以从 10 行中读取 80,000 列意味着我们正在读取 80,000 * 10 * 100 = 80 MB 的数据。它很大,但不足以填满 1.8 GB 堆。所以我想知道为什么堆越来越满。如果数据请求太大而无法填充合理的时间,我希望 Cassandra 返回 TimeOutException 而不是终止。

一个简单的解决方案是增加堆大小,但这只会掩盖问题。读取 80MB 数据不应使 1.8GB 堆满。

我可以调整其他一些 Cassandra 设置来防止 OOM 异常吗?

【问题讨论】:

  • 你能分享nodetool -h localhost info的输出吗?
  • 很遗憾,接下来几天我将无法访问该集群,因此无法共享 nodetool 的输出。我记得它显示在 Cassandra 因 OOM 异常终止之前使用了 80-90% 的堆空间。
  • 您是否在并行写入时读取数据?我有一个类似的问题,通过将默认堆大小 1GB 更改为 3GB 来解决。
  • 不,读取数据时没有正在进行的写入操作。我确信增加堆空间可能会有所帮助。但我试图理解为什么读取 80MB 的数据会使 1.8GB 堆满。

标签: cassandra astyanax


【解决方案1】:

不,当我读取数据时,没有正在进行的写入操作。我是 确保增加堆空间可能会有所帮助。但我正在努力 了解为什么读取 80MB 数据会导致 1.8GB 堆满。

Cassandra 使用 Heap 和 OfHeap chaching。 首次加载 80MB 用户数据可能会导致 200-400 MB 的 Java 堆使用量。 (哪个 vm?64 位?) 其次,这个内存被添加到已经用于缓存的内存中。 cassandra 似乎没有释放缓存来服务您的私人查询。可以使总吞吐量有意义。

您是否同时通过增加 MaxHeap 解决了您的问题?

【讨论】:

  • 我通过改变我们的应用逻辑解决了这个问题。似乎不建议在 Cassandra 中读取该数据量。
猜你喜欢
  • 2019-02-05
  • 2015-05-31
  • 2013-04-18
  • 2019-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多