卡桑德拉抛出 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 &lt;keyspace name&gt;' 来获取架构,也可以查看 /var/log/cassandra/system.log 以查找诸如“大分区”和“墓碑”之类的内容 您好,根据您的建议添加了更多问题信息。

以上是关于卡桑德拉抛出 OutOfMemory的主要内容,如果未能解决你的问题,请参考以下文章

无法启动卡桑德拉

是啥导致卡桑德拉大排长龙?

sh 卡桑德拉(ubuntu)

弹簧靴+卡桑德拉

卡桑德拉|Cassandra

卡桑德拉+弹簧数据