2

AWS に 3 ノードの cassandra クラスターがあります。これらのノードは cassandra 1.2.2 を実行しており、8 GB のメモリを搭載しています。デフォルトのヒープまたは 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 を返すことを期待します。

簡単な解決策の 1 つは、ヒープ サイズを増やすことですが、それでは問題が見えなくなるだけです。80MB のデータを読み取っても、1.8GB のヒープがいっぱいになることはありません。

OOM 例外を防ぐために微調整できる他の Cassandra 設定はありますか?

4

1 に答える 1

0

いいえ、データを読み取ったときに進行中の書き込み操作はありません。ヒープスペースを増やすと役立つと確信しています。しかし、80MB のデータを読み取ると 1.8GB のヒープがいっぱいになる理由を理解しようとしています。

Cassandra は Heap と OfHeap のチャッシングを使用します。80MB のユーザーデータを最初にロードすると、200 ~ 400 MB の Java ヒープが使用される場合があります。(どの vm? 64 ビット?) 次に、このメモリは、既にキャッシュに使用されているメモリに追加されます。cassandra は、プライベート クエリを提供するためにそのキャッシュを解放していないようです。全体的なスループットは理にかなっている可能性があります。

その間、MaxHeap を増やして問題を解決しましたか?

于 2013-10-31T10:44:02.777 に答える