禁用交换(swapping)

大多数操作系统都试图将尽可能多的内存用于文件系统缓存,并急切地交换出未使用的应用程序内存。 这可能导致部分 JVM 堆甚至其可执行页面被换出到磁盘。

交换(swapping) 对性能和节点稳定性非常不利,应该不惜一切代价避免。 这可能导致垃圾回收持续几分钟而不是几毫秒,并可能导致节点响应缓慢,甚至与集群断开连接。 在弹性分布式系统中,让操作系统杀死节点更有效。

有三种方法可以禁用交换。 首选的选项是完全禁用交换。 如果这不是一个选项,那么是否更倾向于最小化交换性而不是内存锁定取决于你的环境。

禁用所有交换文件

通常 Elasticsearch 是唯一运行在机器上的服务,它的内存使用由 JVM 选项控制。 应该不需要启用交换。

在Linux系统上,您可以通过运行以下命令来临时禁用交换:

sudo swapoff -a

这不需要重启 Elasticsearch。

要永久禁用它,需要编辑 /etc/fstab 文件并注释掉任何包含单词 swap 的行。

在 Windows 上,可以通过 System Properties → Advanced → Performance → Advanced → Virtual memory 完全禁用分页文件来实现相同的效果。

配置 交换性(swappiness)

Linux系统上的另一个选项是确保 sysctl 值 vm.swappiness 设置为 1。 这降低了内核交换的倾向,并且在正常情况下不会导致交换,同时仍然允许整个系统在紧急情况下进行交换。

启用 bootstrap.memory_lock

另一种选择是在Linux/Unix系统上使用mlockall,或者在 Windows 上使用 VirtualLock,尝试将进程地址空间锁定到 RAM 中,防止任何 Elasticsearch 内存被换出。 这可以通过将下面这一行添加到 config/elasticsearch.yml 文件中来实现:

bootstrap.memory_lock: true

如果试图分配比可用内存更多的内存,mlockall 可能会导致 JVM 或 shell 会话退出!

启动 Elasticsearch 后,可以通过检查下面这个请求输出中的 mlockall 值来查看该设置是否成功应用:

GET _nodes?filter_path=**.mlockall

如果你看到mlockallfalse,那么这意味着 mlockall 请求已经失败。 你还会在日志中看到一行包含更多信息的文字:Unable to lock JVM Memory

在Linux/Unix系统上,最可能的原因是运行 Elasticsearch 的用户没有锁定内存的权限。 可以按以下方式授予权限:

使用 .zip.tar.gz 归档文件安装的:
在启动 Elasticsearch 前, 以 root 身份设置 ulimit -l unlimited,或者在 /etc/security/limits.conf 文件中设置 memlockunlimited
使用 RPM 和 Debian 包安装的:
系统配置文件 中设置 MAX_LOCKED_MEMORYunlimited (或者参见下面使用systemd的系统)。
使用 systemd 的系统:
systemd 配置 中设置 LimitMEMLOCKinfinity

另一个可能导致 mlockall 失败的原因是 JNA临时目录(通常是/tmp的一个子目录) 是使用选项 noexec 挂载的。 这可以通过使用 ES_JAVA_OPTS环境变量为 JNA 指定一个新的临时目录来解决:

export ES_JAVA_OPTS="$ES_JAVA_OPTS -Djna.tmpdir=<path>"
./bin/elasticsearch

或者在 jvm.options 配置文件中设置这个 JVM 标志。