我正在运行一个 JVM 来支持 ElasticSearch。我仍在进行大小调整和调优,因此我将 JVM 的最大堆大小保留为 ElasticSearch 的默认值 1GB。将数据放入数据库后,我发现 JVM 的进程在top
输出中显示 SIZE 为 50GB。看来这实际上导致了系统的性能问题;其他进程在分配内存时遇到了麻烦。
在询问 ElasticSearch 社区时,他们表示这“只是”文件系统缓存。根据我的经验,文件系统缓存不会显示为特定进程使用的内存。当然,他们可能谈论的是操作系统文件系统缓存以外的其他内容,可能是 JVM 或 ElasticSearch 本身在操作系统之上执行的操作。但他们还表示,如果需要,它会被释放,但这似乎没有发生。
因此,有人能帮助我弄清楚如何调整 JVM 或者 ElasticSearch 本身,以不使用太多 RAM 吗?
系统是 Solaris 10 x86,配备 72GB RAM。JVM 是“Java(TM) SE 运行时环境(build 1.7.0_45-b18)”。
答案1
我很确定您从 ElasticSearch 社区获得的答案与 ZFS ARC(自适应替换缓存)有关。这当然假设您的文件系统是 ZFS?
在 ZFS 上,ARC 可能会占用主机上所有可用 RAM(少于 1 GB)。因此,在 ZFS 主机上,类似工具top
有时会显示您的物理 RAM 接近极限,即使事实并非如此。这是设计使然。ARC 会自动将内存释放给需要内存的进程。ARC 使用的内存计入内核内存,因此您无法在进程输出中真正看到它。
在我每天查看的大多数 Solaris 系统中,物理 RAM 消耗量约为 90%。这并不是因为它们利用率很高,而是 ZFS 会将未使用的 RAM 用于自己的目的。不要对此感到惊慌。由于 ARC 是内核的一部分,它可以以光速将内存释放给需要它的进程。因此 - 虽然你可以 - 我通常认为没有必要限制 ZFS ARC 的大小。最好让 ZFS 完成它的工作。
因此,如果我们谈论的是 ZFS,那么是的,文件系统缓存不会显示为单个进程的内存消耗。您需要执行类似以下操作:
echo "::memstat" | mdb -k
揭示内存的实际使用情况。“Anon”行涵盖了您在prstat
输出中看到的所有用户空间进程。
您需要了解的另一件事是 JVM 在内存分配和释放方面的工作原理。JVM 根据需要从操作系统获取内存,但仅受 JVM 的限制-Xmx
命令行参数的限制。悬而未决的问题是,如果 JVM 不再需要内存,它将如何(如果有的话)将其释放回操作系统?您会发现很难找到有关此主题的信息。这似乎取决于使用哪种垃圾收集器。由于很难获得有关此主题的精确信息(真的不知道为什么),因此您最好的选择是假设 JVM 是极不情愿将内存释放回操作系统。换句话说:如果你允许 JVM 进程获取 50 GB 内存,那么你最好能够承受这一点永久而不是假设这只是一次爆发。
因此,如果你想限制 ElasticSearch 进程可以消耗的内存量,那么你需要研究JVM命令行参数,特别是-Xmx
选项。