AWS에는 3 노드 카산드라 클러스터가 있습니다. 이 노드는 cassandra 1.2.2를 실행하며 8GB 메모리를 가지고 있습니다. 우리는 기본 힙이나 GC 설정을 변경하지 않았습니다. 따라서 각 노드는 1.8GB의 힙 공간을 할당합니다. 행은 넓습니다. 각 행에는 약 26 만 개의 열이 저장됩니다. Astyanax를 사용하여 데이터를 읽습니다. 우리 응용 프로그램이 동시에 10 개 이상의 행에서 80,000 개의 열을 읽으려고하면 일부 노드가 힙 공간을 모두 소모하여 OOM 오류로 종료됩니다. 다음은 오류 메시지입니다.카산드라는 OutOfMemory (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 = 80MB의 데이터를 읽음을 의미합니다. 크기는 크지 만 1.8GB 힙을 채울만큼 크지 않습니다. 그래서 왜 힙이 가득 차게되는지 궁금합니다. 합리적인 시간을 채우기 위해 데이터 요청이 커지면 Cassandra가 종료 대신 TimeOutException을 반환 할 것으로 기대합니다.
하나의 쉬운 솔루션은 힙 크기를 늘리는 것이지만 문제는 단지 마스크 만됩니다. 80MB의 데이터를 읽으면 1.8GB 힙이 가득 채워져서는 안됩니다.
OOM 예외를 방지하기 위해 조정할 수있는 다른 카산드라 설정이 있습니까?
'nodetool -h localhost info'의 출력을 공유 할 수 있습니까? – abhi
불행히도 앞으로 며칠 동안 해당 클러스터에 액세스 할 수 없으므로 nodetool의 출력을 공유 할 수 없습니다. Cassandra가 OOM 예외로 종료하기 전에 80-90 %의 힙 공간을 보여주는 것을 기억합니다. –
쓰기가 병렬로 진행되는 동안 데이터를 읽으십니까? 나는 1GB의 기본 힙 크기를 3GB로 변경하여 해결 된 비슷한 문제를 겪었습니다. –