Cassandra耗尽内存(堆空间)

时间:2012-04-03 13:55:57

标签: amazon-ec2 cassandra

我们最近正在尝试Cassandra(版本1.0.7),我们似乎有一些内存问题。我们使用EC2作为我们的测试环境,我们有三个节点,3.7G内存和1个核心@ 2.4G,都运行Ubuntu服务器11.10。

问题是我们从thrift接口命中的节点定期死亡(大约在我们存储2-2.5G的数据之后)。错误消息:OutOfMemoryError:Java堆空间,根据日志,它实际上使用了所有已分配的内存。

节点处于相对恒定的负载下,每分钟存储大约2000-4000行密钥,这些密钥通过Trift接口一次性分批10-30行(每个大约50列)。读取次数非常低,每天大约1000-2000,只请求单行密钥的数据。目前只有一个使用过的列族。

最初的想法是cassandra-env.sh文件中出现了问题。因此,我们根据节点的规范指定了变量'system_memory_in_mb'(3760)和'system_cpu_cores'(1)。我们还将'MAX_HEAP_SIZE'更改为2G,将'HEAP_NEWSIZE'更改为200M(我们认为第二个与垃圾收集相关)。不幸的是,这并没有解决问题,而且我们通过节俭打击的节点会不断定期死亡。

如果你发现这个有用,交换关闭并且所有3台服务器上的不可用内存似乎都非常高(2.3GB,我们通常会观察到大约0-16KB的其他Linux服务器上的不可预测内存量)(我们是不太确定不可挽回的记忆如何与Cassandra联系起来,这只是我们在研究这个问题时所观察到的事情。 CPU一直都很空闲。根据nodetool,堆内存显然会偶尔减少,但随着时间的推移显然会超过限制。

有什么想法吗?提前谢谢。

2 个答案:

答案 0 :(得分:3)

cassandra-env.sh默认值几乎适用于所有工作负载,所以在你知道为什么这种情况最好将它们恢复到默认值之前,或者你可能会在没有意识到的情况下让事情变得更糟。

我在集群上看到2k / sec / node的并发读写,所以每分钟2k-4k写入非常少,尽管它只是接受你的连接的节点正在死亡这一事实有点奇怪。

如果您将应用程序连接到其他节点之一上的thrift端点,那么它是否会死亡? 客户端连接使用内存,因此可能值得仔细检查一次不要连接太多。垂死的cassandra节点上的“ netstat -A inet | grep 9160 ”应告诉您有多少客户端连接。很大程度上取决于您的应用程序,您可能需要10s或100s而不是1000s。

写入是什么样的?
您是否重复编写相同的行键,如果是这样,您是否附加新的列名或覆盖相同的行名? 每次写多大?还有别的什么可以告诉我吗? 如果你在相同的行键中覆盖相同的列名,那么压缩可能会一直困难。 如果您经常将新列名称附加到相同的行键,则可能会使行太大而无法放入内存中。

垂死节点上“nodetool -h localhost tpstats”的输出也可能会提供一些关于你跌落的地方的线索。任何不断发布的事情都可能是坏消息,特别是在如此低的写入率下。

如果你要在生产中使用cassandra,你应该对内部结构进行图形化,以便更好地了解正在发生的事情。 jmxtrans和graphite应该是你最好的朋友。

答案 1 :(得分:2)

有些事情可以尝试调整。首先确保您的列族没有行缓存。检查日志中的错误和tpstats也值得,因为错误导致某些事情死亡,并且某些事情正在队列中备份。异常的堆栈跟踪也很有意义,因为实际上有不同类型的OOM可能只是意味着内核调整。

如果您只是为每个节点使用了太多的内存,那么您想要了解数据集的大小,请尝试检查cfstats,您可以大致确定在bloom过滤器上花费了多少空间。由于CF中有更多行,因此可以线性增大,并且是节点所需的基本最小内存的一部分。

nodetool cfstats | grep Bloom.*Used | awk '{ SUM += $5} END { print SUM " bytes" }'

由于你不经常阅读,你可能会增加它们的误报率。每个SSTable都有一个布隆过滤器,用于检查是否存在行。您可以使用cqlsh

进行更改
ALTER TABLE MyColumnFamily WITH bloom_filter_fp_chance = 0.1;

之后调用每个节点的CF升级(这将很慢)

nodetool upgradesstables MyKeyspace MyColumnFamily

这会导致读取的后果可能需要更长的时间,因为有10%-ish(.1)的可能性会检查SSTables中不存在的行,导致额外的磁盘搜索。

如果列族具有大量行,则另一个主要的内存接收器是索引的采样率。这可以在cassandra.yaml

中按节点级别进行修改

http://www.datastax.com/docs/1.1/configuration/node_configuration#index-interval

如果你将它设置为在OOM上进行堆转储(默认情况下我认为-XX:+ HeapDumpOnOutOfMemoryError),那么/ var / lib / cassandra / data目录中应该有一些堆转储可用。您可以在visualvm或任何您喜欢的工具中打开它们,以确定堆的哪个部分位于何处。

相关问题