Cassandra:压缩时的内存消耗

Cassandra : memory consumption while compacting

我在 system.log 中收到 ParNew GC 警告,暂停时间超过 8 秒:

WARN  [Service Thread] GCInspector.java:283 - ParNew GC in 8195ms.  CMS Old Gen: 22316280488 -> 22578261416; Par Eden Space: 1717787080 -> 0; Par Survivor Space: 123186168 -> 214695936

它似乎出现在特定 table 上发生较小的压实时:

92128ed0-46fe-11ec-bf5a-0d5dfeeee6e2 ks table 1794583380  1754598812  {1:92467, 2:5291, 3:22510}                                                                  
f6e3cd30-46fc-11ec-bf5a-0d5dfeeee6e2 ks table 165814525   160901558   {1:3196, 2:24814}                                                                           
334c63f0-46fc-11ec-bf5a-0d5dfeeee6e2 ks table 126097876   122921938   {1:3036, 2:24599}       

table :

heap size 是 32GB。

问题:

一个。在压缩过程中有多少行必须适合内存(一次!)?它只是一个,还是更多?

b。压缩时,每个分区是在 decompressed form 中读入内存,还是在 compressed form 中读入?

c。你认为我的压缩过程会填满所有堆内存吗?

谢谢

完整的 GC 设置:

-Xms32G
-Xmx32G
#-Xmn800M
-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:+CMSParallelRemarkEnabled
-XX:SurvivorRatio=8
-XX:MaxTenuringThreshold=1
-XX:CMSInitiatingOccupancyFraction=75
-XX:+UseCMSInitiatingOccupancyOnly
-XX:CMSWaitDuration=10000
-XX:+CMSParallelInitialMarkEnabled
-XX:+CMSEdenChunksRecordAlways

a. how many rows must fit into memory (at once!) during compaction process ? It is just one, or more ?

肯定是多个

b. while compacting, does each partition is read in decompressed form into memory, or in compressed form ?

压缩仅适用于磁盘级别。在压缩可以对其进行任何操作之前,它需要解压缩并读取它。

c. do you think the compaction process in my case could fill up all the heap memory ?

是的,压缩过程会分配大量堆,运行 压缩会导致已经紧张的堆出现问题。

TBH,我看到了几个改进列出的 GC 设置的机会。而现在,我认为这就是大多数问题所在。让我们从新一代尺寸开始:

#-Xmn800M

使用 CMS,您绝对需要明确您的堆新大小 (Xmn)。特别是有一个巨大的堆。是的,对于 CMS,32GB 是“巨大的”。每个 CPU 核心智慧 100MB 是不正确的。对于 Cassandra,新堆大小应在最大堆大小 (Xmx) 的 25% 到 50% 范围内。对于 32GB,我会说取消注释 Xmn 行并将其设置为 -Xmn12G.

下面是为 CMS 映射内存的方式:

现在让我们看看这两个:

-XX:SurvivorRatio=8
-XX:MaxTenuringThreshold=1

线性布局,堆分为 new/young 代、老年代和永久代。主要,stop-the-world collections 发生在 inter-generational 晋升(例如:新世代到旧世代)。

在新世代中,它分为伊甸园space和幸存者spaceS0和S1。你想要的,是你所有的 object 都在新一代 space 中被创造、生存和死亡。为此,MaxTenuringThreshold(object 可以在幸存者 space 之间复制多少次)需要更高。此外,幸存者 space 需要足够大才能承受重量。以 1:8 的比率,每个幸存者 space 将是伊甸园 space 的 1/8。所以我会选择这些,只是为了开始:

-XX:SurvivorRatio=2
-XX:MaxTenuringThreshold=6

这将使幸存者 spaces 变大,并允许 objects 在它们之间传递 6 次。希望这段时间足够长,可以避免宣传它们。

添加这些也会有所帮助:

-XX:+AlwaysPreTouch
-XX:+UseTLAB
-XX:+ResizeTLAB
-XX:-UseBiasedLocking

有关这些的更多信息 ^ 查看 Amy's Cassandra 2.1 Tuning Guide。但是对于 Cassandra,您确实希望“预接触”,您确实希望启用线程本地分配块 (TLAB),您确实希望能够调整这些块的大小,并且您不希望偏向锁定。

选择您的一个节点,进行这些更改,重新启动并监控性能。如果他们有帮助(我认为他们会的),也将它们添加到其余节点。

tl;dr;

我会进行以下更改:

-Xmn12G
-XX:SurvivorRatio=2
-XX:MaxTenuringThreshold=6
-XX:+AlwaysPreTouch
-XX:+UseTLAB
-XX:+ResizeTLAB
-XX:-UseBiasedLocking

参考文献:

  • CASSANDRA-8150 - 更改默认 JVM 设置的最终失败尝试。但随后的讨论产生了 JVM 调优智慧的最佳汇编之一。
  • Amy's Cassandra 2.1 Tuning Guide - 它可能已过时,但这仍然是最全面的 Cassandra 管理指南之一。讨论的许多设置和方法仍然非常相关。