故障排除和修复 Cassandra OOM 问题

Troubleshooting and fixing Cassandra OOM issue

尽管有多个关于 OOM 问题的线程想要澄清某些事情。我们是 运行 K8 中的 36 节点 Cassandra 集群 3.11.6 版本,为容器分配了 32gigs。

容器正在 OOM 终止(注意:- 不是 java 堆 OOM 错误而是 linux cgroup OOM 杀手)因为它达到了其 cgroup 的 32 gig 内存限制。

统计和配置

map[limits:map[ephemeral-storage:2Gi memory:32Gi] requests:map[cpu:7 ephemeral-storage:2Gi memory:32Gi]]

Cgroup内存限制 34359738368 -> 32 Gigs

JVM spaces 由 Cassandra 自动计算 -Xms19660M -Xmx19660M -Xmn4096M

Grafana Screenshot

Cassandra Yaml --> https://pastebin.com/ZZLTc1cM

JVM 选项 --> https://pastebin.com/tjzZRZvU

已消耗 98% 内存的节点上的 Nodetool 信息输出

nodetool info
ID                     : 59c53bdb-4f61-42f5-a42c-936ea232e12d
Gossip active          : true
Thrift active          : true
Native Transport active: true
Load                   : 179.71 GiB
Generation No          : 1643635507
Uptime (seconds)       : 9134829
Heap Memory (MB)       : 5984.30 / 19250.44
Off Heap Memory (MB)   : 1653.33
Data Center            : datacenter1
Rack                   : rack1
Exceptions             : 5
Key Cache              : entries 138180, size 99.99 MiB, capacity 100 MiB, 9666222 hits, 10281941 requests, 0.940 recent hit rate, 14400 save period in seconds
Row Cache              : entries 10561, size 101.76 MiB, capacity 1000 MiB, 12752 hits, 88528 requests, 0.144 recent hit rate, 900 save period in seconds
Counter Cache          : entries 714, size 80.95 KiB, capacity 50 MiB, 21662 hits, 21688 requests, 0.999 recent hit rate, 7200 save period in seconds
Chunk Cache            : entries 15498, size 968.62 MiB, capacity 1.97 GiB, 283904392 misses, 34456091078 requests, 0.992 recent hit rate, 467.960 microseconds miss latency
Percent Repaired       : 8.28107989669628E-8%
Token                  : (invoke with -T/--tokens to see all 256 tokens)

做了什么

  1. 我们已经确保 cassandra 进程没有内存泄漏,因为我们有自定义触发代码。 Gc 日志 analytics 显示我们占用了大约 14 GB 的 jvm space.

问题

尽管我们知道 cassandra 确实占用堆 spaces(Bloom 过滤器、Memtables 等)

  1. grafana 截图显示节点占用了 32 个 gig 的 98%。 JVM heap = 19.5 gigs + offheap space in nodetool info output = 1653.33 MB (1Gigs) (JVM heap + off heap = 22 gigs)。剩余内存(10 gigs)在哪里?如何准确计算占用剩余内存的内容。 (由于抱怨原因,Nodetool tablestats 和 nodetool cfstats 输出未共享)?

我们的生产集群需要大量批准,因此使用 jconsole 远程部署它们很困难。考虑此内存使用情况的任何其他方式。

  1. 一旦我们计算了内存使用情况,下一步是什么来解决这个问题并避免 OOM 终止?

SSTables 很有可能被映射到内存(使用 mmap() 缓存)。如果是这种情况,它不会立即生效,并且内存使用量会随着时间的推移而增长,具体取决于何时读取 SSTables,然后将其缓存。我在 https://community.datastax.com/questions/6947/.

中写过这个问题

称为“磁盘访问模式”的 not-so-well-known 配置 属性 存在问题。如果未设置 cassandra.yaml,它默认为 mmap,这意味着所有 SSTables 都会 mmaped 到内存。如果是这样,您将在启动时在 system.log 中看到一个条目,如下所示:

INFO  [main] 2019-05-02 12:33:21,572  DatabaseDescriptor.java:350 - \
  DiskAccessMode 'auto' determined to be mmap, indexAccessMode is mmap

解决方案是通过设置将磁盘访问模式配置为仅缓存 SSTable 索引文件(而不是 *-Data.db 组件):

disk_access_mode: mmap_index_only

有关详细信息,请参阅我上面发布的 link。干杯!