卡桑德拉抛出 OutOfMemory
Posted
技术标签:
【中文标题】卡桑德拉抛出 OutOfMemory【英文标题】:Cassandra throws OutOfMemory 【发布时间】:2017-06-16 17:16:23 【问题描述】:在我们的测试环境中,我们有一个 1 节点的 cassandra 集群,所有键空间的 RF=1。
下面列出了感兴趣的 VM 参数
-XX:+CMSClassUnloadingEnabled -XX:+UseThreadPriorities -XX:ThreadPriorityPolicy=42 -Xms2G -Xmx2G -Xmn1G -XX:+HeapDumpOnOutOfMemoryError -Xss256k -XX:StringTableSize=1000003 -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX :+CMSParallelRemarkEnabled -XX:SurvivorRatio=8
我们注意到 Full GC 频繁发生,并且 cassandra 在 GC 期间变得无响应。
INFO [Service Thread] 2016-12-29 15:52:40,901 GCInspector.java:252 - ParNew GC in 238ms. CMS Old Gen: 782576192 -> 802826248; Par Survivor Space: 60068168 -> 32163264
INFO [Service Thread] 2016-12-29 15:52:40,902 GCInspector.java:252 - ConcurrentMarkSweep GC in 1448ms. CMS Old Gen: 802826248 -> 393377248; Par Eden Space: 859045888 -> 0; Par Survivor Space: 32163264 -> 0
我们得到 java.lang.OutOfMemoryError 并出现以下异常
ERROR [SharedPool-Worker-5] 2017-01-26 09:23:13,694 JVMStabilityInspector.java:94 - JVM state determined to be unstable. Exiting forcefully due to:
java.lang.OutOfMemoryError: Java heap space
at java.nio.HeapByteBuffer.<init>(HeapByteBuffer.java:57) ~[na:1.7.0_80]
at java.nio.ByteBuffer.allocate(ByteBuffer.java:331) ~[na:1.7.0_80]
at org.apache.cassandra.utils.memory.SlabAllocator.getRegion(SlabAllocator.java:137) ~[apache-cassandra-2.1.8.jar:2.1.8]
at org.apache.cassandra.utils.memory.SlabAllocator.allocate(SlabAllocator.java:97) ~[apache-cassandra-2.1.8.jar:2.1.8]
at org.apache.cassandra.utils.memory.ContextAllocator.allocate(ContextAllocator.java:57) ~[apache-cassandra-2.1.8.jar:2.1.8]
at org.apache.cassandra.utils.memory.ContextAllocator.clone(ContextAllocator.java:47) ~[apache-cassandra-2.1.8.jar:2.1.8]
at org.apache.cassandra.utils.memory.MemtableBufferAllocator.clone(MemtableBufferAllocator.java:61) ~[apache-cassandra-2.1.8.jar:2.1.8]
at org.apache.cassandra.db.Memtable.put(Memtable.java:192) ~[apache-cassandra-2.1.8.jar:2.1.8]
at org.apache.cassandra.db.ColumnFamilyStore.apply(ColumnFamilyStore.java:1237) ~[apache-cassandra-2.1.8.jar:2.1.8]
at org.apache.cassandra.db.Keyspace.apply(Keyspace.java:400) ~[apache-cassandra-2.1.8.jar:2.1.8]
at org.apache.cassandra.db.Keyspace.apply(Keyspace.java:363) ~[apache-cassandra-2.1.8.jar:2.1.8]
at org.apache.cassandra.db.Mutation.apply(Mutation.java:214) ~[apache-cassandra-2.1.8.jar:2.1.8]
at org.apache.cassandra.service.StorageProxy$7.runMayThrow(StorageProxy.java:1033) ~[apache-cassandra-2.1.8.jar:2.1.8]
at org.apache.cassandra.service.StorageProxy$LocalMutationRunnable.run(StorageProxy.java:2224) ~[apache-cassandra-2.1.8.jar:2.1.8]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) ~[na:1.7.0_80]
at org.apache.cassandra.concurrent.AbstractTracingAwareExecutorService$FutureTask.run(AbstractTracingAwareExecutorService.java:164) ~[apache-cassandra-2.1.8.jar:2.1.8]
at org.apache.cassandra.concurrent.SEPWorker.run(SEPWorker.java:105) [apache-cassandra-2.1.8.jar:2.1.8]
at java.lang.Thread.run(Thread.java:745) [na:1.7.0_80]
我们能够在执行 nodetool 修复后恢复 cassandra。
节点工具状态
数据中心:DC1
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
-- Address Load Tokens Owns Host ID Rack
UN 10.3.211.3 5.74 GB 256 ? 32251391-5eee-4891-996d-30fb225116a1 RAC1
注意:非系统键空间没有相同的复制设置,有效的所有权信息没有意义
节点工具信息
ID : 32251391-5eee-4891-996d-30fb225116a1
Gossip active : true
Thrift active : true
Native Transport active: true
Load : 5.74 GB
Generation No : 1485526088
Uptime (seconds) : 330651
Heap Memory (MB) : 812.72 / 1945.63
Off Heap Memory (MB) : 7.63
Data Center : DC1
Rack : RAC1
Exceptions : 0
Key Cache : entries 68, size 6.61 KB, capacity 97 MB, 1158 hits, 1276 requests, 0.908 recent hit rate, 14400 save period in seconds
Row Cache : entries 0, size 0 bytes, capacity 0 bytes, 0 hits, 0 requests, NaN recent hit rate, 0 save period in seconds
Counter Cache : entries 0, size 0 bytes, capacity 48 MB, 0 hits, 0 requests, NaN recent hit rate, 7200 save period in seconds
Token : (invoke with -T/--tokens to see all 256 tokens)
从 System.log 中,我看到很多压缩大分区
WARN [CompactionExecutor:33463] 2016-12-24 05:42:29,550 SSTableWriter.java:240 - Compacting large partition mydb/Table_Name:2016-12-23 00:00+0530 (142735455 bytes)
WARN [CompactionExecutor:33465] 2016-12-24 05:47:57,343 SSTableWriter.java:240 - Compacting large partition mydb/Table_Name_2:22:0c2e6c00-a5a3-11e6-a05e-1f69f32db21c (162203393 bytes)
对于 Tombstone,我在 system.log 下面注意到
[main] 2016-12-28 18:23:06,534 YamlConfigurationLoader.java:135 - 节点 配置:[验证器=密码验证器; 授权人=卡桑德拉授权人;自动快照=真; batch_size_warn_threshold_in_kb=5; batchlog_replay_throttle_in_kb=1024; cas_contention_timeout_in_ms=1000; client_encryption_options=; cluster_name=银行集市; column_index_size_in_kb=64; commit_failure_policy=忽略; commitlog_directory=/var/cassandra/log/commitlog; commitlog_segment_size_in_mb=32; commitlog_sync=定期; commitlog_sync_period_in_ms=10000; compaction_throughput_mb_per_sec=16;并发计数器写入=32; 并发读取=32;并发写入=32; counter_cache_save_period=7200; counter_cache_size_in_mb=null; counter_write_request_timeout_in_ms=15000;交叉节点超时=假; data_file_directories=[/cryptfs/sdb/cassandra/data, /cryptfs/sdc/cassandra/data, /cryptfs/sdd/cassandra/data]; disk_failure_policy=best_effort; dynamic_snitch_badness_threshold=0.1; dynamic_snitch_reset_interval_in_ms=600000; dynamic_snitch_update_interval_in_ms=100; endpoint_snitch=GossipingPropertyFileSnitch; 提示切换启用=真;提示_handoff_throttle_in_kb=1024; 增量备份=假; index_summary_capacity_in_mb=null; index_summary_resize_interval_in_minutes=60; inter_dc_tcp_nodelay=false;节点间压缩=全部; key_cache_save_period=14400; key_cache_size_in_mb=null; 听地址=127.0.0.1; max_hint_window_in_ms=10800000; max_hints_delivery_threads=2; memtable_allocation_type=heap_buffers; native_transport_port=9042; num_tokens=256; partitioner=org.apache.cassandra.dht.Murmur3Partitioner; permissions_validity_in_ms=2000; range_request_timeout_in_ms=20000; read_request_timeout_in_ms=10000; request_scheduler=org.apache.cassandra.scheduler.NoScheduler; request_timeout_in_ms=20000; row_cache_save_period=0; row_cache_size_in_mb=0; rpc_address=127.0.0.1; rpc_keepalive=true; rpc_port=9160; rpc_server_type=同步; saved_caches_directory=/var/cassandra/data/saved_caches; seed_provider=[class_name=org.apache.cassandra.locator.SimpleSeedProvider, 参数=[种子=127.0.0.1]]; server_encryption_options=; snapshot_before_compaction=false; ssl_storage_port=9001; sstable_preemptive_open_interval_in_mb=50; start_native_transport=真; start_rpc=真;存储端口=9000; thrift_framed_transport_size_in_mb=15; tombstone_failure_threshold=100000; tombstone_warn_threshold=1000; 涓流_fsync=假;涓流_fsync_interval_in_kb=10240; truncate_request_timeout_in_ms=60000; write_request_timeout_in_ms=5000]
nodetool tpstats
Pool Name Active Pending Completed Blocked All time blocked
CounterMutationStage 0 0 0 0 0
ReadStage 32 4061 50469243 0 0
RequestResponseStage 0 0 0 0 0
MutationStage 32 22 27665114 0 0
ReadRepairStage 0 0 0 0 0
GossipStage 0 0 0 0 0
CacheCleanupExecutor 0 0 0 0 0
AntiEntropyStage 0 0 0 0 0
MigrationStage 0 0 0 0 0
Sampler 0 0 0 0 0
ValidationExecutor 0 0 0 0 0
CommitLogArchiver 0 0 0 0 0
MiscStage 0 0 0 0 0
MemtableFlushWriter 0 0 7769 0 0
MemtableReclaimMemory 1 57 13433 0 0
PendingRangeCalculator 0 0 1 0 0
MemtablePostFlush 0 0 9279 0 0
CompactionExecutor 3 47 169022 0 0
InternalResponseStage 0 0 0 0 0
HintedHandoff 0 1 148 0 0
是否有任何 YAML/其他配置可用于避免“大压缩”
要使用的正确压缩策略是什么?错误的 Compaction Strategy 会导致 OutOfMemory
在其中一个键空间中,我们为每一行写入一次并读取多次。
对于另一个键空间,我们有时间序列类型的数据,它只插入和多次读取
【问题讨论】:
仅供参考 - 在单节点集群中运行nodetool repair
对您没有帮助,因为它没有任何其他节点可以向/从流式传输数据。
【参考方案1】:
看到这个:堆内存 (MB): 812.72 / 1945.63 告诉我您的 1 台机器可能电源不足。您很有可能无法跟上 GC 的步伐。
虽然在这种情况下,我认为这可能与尺寸过小有关 - 访问模式、数据模型和有效负载大小也会影响 GC,因此如果您想使用该信息更新您的帖子,我可以更新我的答案反映这一点。
编辑以反映新信息
感谢您添加更多信息。根据您发布的内容,我注意到有两件事会立即导致您的堆崩溃:
大分区:
看起来压缩必须压缩超过 100mb(分别为 140 和 160mb)的 2 个分区。通常情况下,这仍然是ok(不是很好),但是因为你是在具有如此小堆的供电硬件上运行的,所以这相当多。
关于压缩的事情
它在运行时使用了健康的资源组合。一切照旧,因此您应该对其进行测试和计划。在这种情况下,我确信由于使用 CPU 资源(GC 需要)、堆和 IO 的大分区,压缩工作更加努力。
这让我想到了另一个问题:
Pool Name Active Pending Completed Blocked All time blocked
CounterMutationStage 0 0 0 0 0
ReadStage 32 4061 50469243 0 0
这通常表明您需要扩大和/或扩大规模。在您的情况下,您可能希望两者都做。使用未优化的数据模型,您可以很快耗尽单个功率不足的节点。当您在单节点环境中进行测试时,您也不会体验到分布式系统的细微差别。
所以 TL;DR:
对于读取繁重的工作负载(这似乎是),您将需要更大的堆。对于所有的健全性和集群健康,您需要重新访问您的数据模型以确保分区逻辑是合理的。如果您不确定如何或为什么要这样做,我建议您花一些时间在这里:https://academy.datastax.com/courses
【讨论】:
您能否告诉我如何获取您要求的“访问模式、数据模型和有效负载大小”信息?是否有任何特定的 nodetool 命令? 访问模式和有效负载大小是应用程序开发人员应该注意的事情。您可以运行cqlsh -e 'DESCRIBE KEYSPACE <keyspace name>'
来获取架构,也可以查看 /var/log/cassandra/system.log 以查找诸如“大分区”和“墓碑”之类的内容
您好,根据您的建议添加了更多问题信息。以上是关于卡桑德拉抛出 OutOfMemory的主要内容,如果未能解决你的问题,请参考以下文章