Cassandra 2.1 集群显示持续高 CPU 使用率和缓慢响应

Cassandra 2.1 Cluster Showing Consistently High CPU Usage and Slow Responses

5 月 3 日我们部署了。我们的 3 节点 cassandra 集群变得极其缓慢,许多 Web 请求都超时了。到 EOD 5 月 3 日,我们向集群启动了另一台 m1.large 机器,解决了超时问题。话虽如此,集群仍然非常慢; 5 月 4 日,我们启动了五个 i3.xLarge 节点。这极大地帮助了我们的应用程序响应时间,5 月 5 日我们从集群中删除了旧的 m1.large 框。截至 5 月 5 日 EOD,一切都快速且响应迅速。今天早上,应用程序又开始超时了。

我们注意到一些奇怪的 CPU 使用率行为 - CPU 使用率在 100% 和 200% 之间波动,无论负载如何(它们是四核机器)。我们的周末非常轻,完全没有负载,周一负载相对较重,但我们看到 CPU 使用率绝对没有变化。

正如您在下面的 2 周图表中所见,我们的数据库 CPU 使用量曾经与应用程序使用量绑定。您可以看到 3 日的大峰值,4 日新机器的引入,以及从 6 日开始稳定的高 CPU 使用率。

我们花了很多时间试图确定 CPU 用法的原因,并且能够确定(并随后排除)三个主要原因:

  1. High khugepaged CPU usage.
  2. 垃圾收集调整不当
  3. 压实调整不当

我们已经排除了所有这三种情况。

  1. 我们的服务器有 0.0% khugepaged CPU 使用率。
  2. 我们的 GC 吞吐量约为 96%。我们还调整了堆和新的堆大小,并切换到 G1 GC。我们的日志曾经显示与长时间 GC 暂停相关的警告,但现在不再显示了。此外,GC 线程仅占少量 CPU 使用量。
  3. nodetool compactionstats returns 0 个待处理任务。我们已经切换到 LeveledCompactionStrategy 并将 GC_GRACE_SECONDS 设置为 1 天。我们的日志曾经显示与大量墓碑相关的警告,但现在不再显示了。 nodetool compactionhistory 显示每小时大约一次压缩,根据日志,它们发生得非常快(< 1 秒)。

Cassandra 的 SharedPoolWorker 线程似乎有很高的使用率。这是一个节点的 CPU 使用线程类型(它们看起来都非常相似):

84.6 SharedPoolWorker
22.1 Thrift
13.5 CCompilerThread
11.9 MessagingServiceOutgoing
9.4  MessagingServiceIncoming
3.6  GangworkerParallelGCThreads
1.6  DestroyJavaVM
.3   VMThread
.1   Thread
.1   ScheduledTasks
.1   OptionalTasks
0    ...

检查 SharedPool-Worker 线程的状态表明绝大多数线程处于等待状态,堆栈跟踪如下:

java.lang.Thread.State: WAITING (parking)
    at sun.misc.Unsafe.park(Native Method)
    at java.util.concurrent.locks.LockSupport.park(Unknown Source)
    at org.apache.cassandra.concurrent.SEPWorker.run(SEPWorker.java:85)
    at java.lang.Thread.run(Unknown Source)

我认为这是问题所在,但我不确定为什么 CPU 等待时间可能很少(根据 dstat 始终为 0%)。

现在,有趣的是,任何给定节点上的 运行 nodetool tpstats 显示少量 ReadStage 线程处于活动状态,偶尔会有一两个处于待处理状态。有 none 被阻止,所有时间被阻止,或被丢弃。

这是 nodetool cfstats 的输出,这里是 nodetool netstats:

Mode: NORMAL
Not sending any streams.
Read Repair Statistics:
Attempted: 12229
Mismatch (Blocking): 2
Mismatch (Background): 0
Pool Name                    Active   Pending      Completed   Dropped
Commands                        n/a         0         707576         0
Responses                       n/a         0         859216       n/a

有人知道为什么会发生这种情况吗?我们可以研究任何潜在的东西吗?

这可能与为单次读取扫描的大量墓碑或大量 sstables 有关 - 由于每个请求需要执行大量读取,因此造成持续高 CPU 负载和缓慢响应.

这些症状可以显示,例如,将 STCS 与持续和频繁 更新(更新行,而不是添加新行)数据一起使用。

能否将您的主表的 nodetool tablestats/cfstats 添加到问题中?

问题实际上是我们的 API。它有 GC 问题,导致大量 db read/write 线程被冻结。