2013-06-21 2 views
2

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 예외를 방지하기 위해 조정할 수있는 다른 카산드라 설정이 있습니까?

+0

'nodetool -h localhost info'의 출력을 공유 할 수 있습니까? – abhi

+0

불행히도 앞으로 며칠 동안 해당 클러스터에 액세스 할 수 없으므로 nodetool의 출력을 공유 할 수 없습니다. Cassandra가 OOM 예외로 종료하기 전에 80-90 %의 힙 공간을 보여주는 것을 기억합니다. –

+0

쓰기가 병렬로 진행되는 동안 데이터를 읽으십니까? 나는 1GB의 기본 힙 크기를 3GB로 변경하여 해결 된 비슷한 문제를 겪었습니다. –

답변

0

아니요, 데이터를 읽을 때 진행중인 쓰기 작업이 없습니다. 나는 힙 공간을 늘리는 것이 도움이 될 수 있음을 확신합니다. 그러나 나는 8035MB의 데이터를 읽는 것이 1.8GB 힙을 가득 채우는 이유를 이해하기 위해 을 시도하고있다.

카산드라는 힙 및 OfHeap을 사용합니다. 80MB 사용자 데이터를 처음로드하면 200-400MB의 Java 힙 사용이 발생할 수 있습니다. (어떤 vm? 64 비트?) 두 번째로이 메모리는 캐시에 이미 사용 된 메모리에 추가됩니다. 카스 산드라가 비공개 쿼리를 제공하기 위해 캐시를 비우지 않는 것처럼 보입니다. 과도한 처리량을 낼 수 있습니다.

MaxHeap을 늘려 문제를 해결 했습니까?

+0

응용 프로그램 논리를 변경하여이 문제를 해결했습니다. Cassandra에서는 데이터 양이 권장되지 않는 것으로 보입니다. –

관련 문제