1

我在 AWS 上有一个 9 个节点的集群。最近有些节点宕机了,我想重启后修复集群。但是我发现修复操作会导致大量的 memtable 刷新,然后 JVM GC 失败。因此,节点挂起。

我正在使用 cassandra 3.1.0。

java version "1.8.0_231"
Java(TM) SE Runtime Environment (build 1.8.0_231-b32)
Java HotSpot(TM) 64-Bit Server VM (build 25.231-b32, mixed mode)

节点硬件为 32GB 内存和 4 核 CPU。堆为 16GB。对于每个节点,大约 200 GB sstables。

JVM 挂起非常快。修复过程开始后,一切正常。我检查了内存、cpu 和 IO。没有发现压力。随机时间后(流式任务完成),memtableflushwriter 挂起任务增长非常快,然后 GC 失败。JVM 挂起并创建了堆转储。问题发生时,CPU 使用率较低,并且我在 AWS EBS 磁盘指标上找不到 I/O 延迟。

我检查了堆转储文件。表修复有几个大的memtables对象。memtable 对象大小约为 400 - 700MB。并且 memtables 在 20 秒内创建。另外,我可以看到超过 12000 个 memtables。在这些 memtables 中,有 6000 个 sstable_activity memtables。

起初,我怀疑 memtable 刷新写入器是瓶颈。所以我把它增加到4个线程。我将节点的内存加倍。但它不起作用。在修复过程中,挂起的任务增加很快,然后节点再次挂起。我还减少了修复令牌范围,只有一个 vnode,但仍然失败。

我们可以看到一些这样的日志

WARN [STREAM-IN-/10.0.113.12:7000] 2020-04-02 05:05:57,150 BigTableWriter.java:211 - Writing large partition ....

写入 sstables 有 300 - 500 MB。一些大的达到 2+ GB。

我浏览了 cassandra 源代码。而且我发现如果表具有物化视图,则必须在正常写入过程中处理 sstables。所以我怀疑这个问题发生在流媒体的 COMPLETE 阶段。

流式传输后,接收回调函数加载更新的分区 sstables 并像正常写入一样创建突变。所以它增加了堆中的内存表。此外,它还调用flush(),这将在修复的表之外创建额外的memtables。内存表大小超过清理阈值。所以叫冲洗。但是刷新不能释放足够的内存。这么多次同花跟注。另一方面,刷新也会增加内存表。

所以有人遇到同样的问题吗?如果我的结论是正确的,如何解决?

4

1 回答 1

1

Cassandra 中的修复不使用 memtable - 它使用用于引导节点等的相同流机制。但是如果您有大分区并且它们已损坏,那么 Cassandra 将需要在接收方发送它们它将需要建造辅助结构等。您可以在以下博客文章中找到有关修复可能出现的问题的更多信息。

一种可能的解决方案是使用范围修复,因此您只能检查令牌环的特定部分。但是手动执行此操作是一项繁琐的任务,因此最好使用Cassandra Reaper之类的工具来自动执行此过程。

于 2020-04-04T16:01:09.007 回答