c# - Cassandra 大量插入时内存不足

标签 c# cassandra

我正在尝试插入具有大列值 (1-25Mb) 的数据,几秒钟后,我的一个节点因抛出 OOM 或陷入无休止的 GC 循环而死亡。

它通常会尝试刷新 CF,但随后显示无法减少堆使用,因为没有脏列族

由于日志建议我减少内存表/缓存大小,我试图弄清楚是什么用完了所有这些内存以调整我的设置,所以我运行了 nodetool flush/invalidaterowcache/invalidatekeycache然后通过jconsole触发GC。

不幸的是,即使服务器处于空闲状态,我的内存使用率仍然很高 (>60%)。

所以,我的问题是为什么服务器在插入大值时内存不足?而且,为什么服务器不回馈一些内存?

编辑

我做了一个 heapdump,堆里全是 byte[],主要由 org.apache.cassandra.io.sstable.IndexSummary$KeyPosition 引用。

我不明白这是怎么可能的,因为一切都应该被刷新。

最佳答案

在我看来你点击了infamous memory fragmentation问题。我不确定 Cassandra 是否消除了一些碎片化问题,但一般来说,在 .NET 和可能的任何 Windows 程序中,都可能遇到这个问题。

当您选择超过 85000 字节(是的,奇数,但确实如此)时,对象将存储在大对象堆中。 LOH 仅作为第 2 代进行 GC,但更糟糕的是,它从不 被压缩。部分原因是the way the OS is implemented引起的.

结果:当您存储 2MB、5MB、3MB、2MB、3MB 的对象并且 2MB 的对象被 GC 处理时,您可能有 4MB 的空闲空间。但是,如果您随后尝试创建一个 3MB 的新对象,由于碎片(2MB 的 2 个孔),它不能被放置在那里并移动到堆的顶部。最终,这会耗尽空间。所以:可能有足够的可用内存,但由于这种碎片,您无论如何都会遇到 OOM

此问题主要出现在 64 位 (WOW64) 和 32 位 Windows 上的 32 位 x86 应用程序上。 64 位应用程序也有碎片问题,但由于虚拟内存要大得多,所以在遇到实际碎片问题之前,您首先要对内存进行分页(变得非常慢)。

如果这确实是问题所在(您可以使用 VMMapWinDbg 直观地检查碎片),您可以通过创建一个大的字节池并重用您自己的池来解决它,从而防止碎片化。

关于c# - Cassandra 大量插入时内存不足,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9920961/

相关文章:

c# - linq 的内部左连接返回太多结果

cassandra - Cassandra世界里的只读副本相当于什么?

Cassandra SUM(Map <text,int>) 可能吗?

scala - 如何在play框架中通过scala连接到cassandra

c# - 在不阻塞的情况下建立和验证来自客户端的连接的最佳方法是什么?

c# - 尝试序列化异常时忽略自定义解析器

c# - 多线程与数据库

c# - 使用Moq,如何检测按钮单击是否触发了 View 模型中的事件?

Cassandra 查询结果各不相同

hadoop - 针对 cassandra 使用 hadoop mapreduce 的示例代码