Cassandra节点JVM在节点修复具有物化视图的表时挂起



我在AWS上有一个9个节点的集群。最近,一些节点出现故障,我想在重新启动它们后修复集群。但我发现修复操作会导致大量内存表刷新,然后JVM GC失败。因此,节点挂起。

我使用的是卡桑德拉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个memtable。在这些成员表中,有6000个sstable_activity成员表。

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

我们可以看到一些类似的日志

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

写字台有300-500兆字节。一些大的达到2 GB以上。

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

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

那么有人遇到同样的问题吗?如果我的结论是正确的,如何修正?

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

一种可能的解决方案是使用范围修复,因此您只能检查令牌环的特定部分。但手动完成这项工作是一项乏味的任务,所以最好使用像Cassandra Reaper这样的工具来自动化这一过程。

最新更新