禁用交换编辑

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

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

有三种方法可以禁用交换。首选选项是完全禁用交换。如果这不是一个选项,那么是优先最小化交换还是内存锁定取决于您的环境。

禁用所有交换文件编辑

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

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

sudo swapoff -a

这不需要重新启动 Elasticsearch。

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

在 Windows 上,可以通过 系统属性 → 高级 → 性能 → 高级 → 虚拟内存 完全禁用页面文件来实现相同的效果。

配置 swappiness编辑

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

启用 bootstrap.memory_lock编辑

另一个选择是在 Linux/Unix 系统上使用 mlockall,或在 Windows 上使用 VirtualLock,尝试将进程地址空间锁定到 RAM 中,防止任何 Elasticsearch 堆内存被交换出去。

某些平台在使用内存锁定时仍然会交换堆外内存。为了防止堆外内存交换,请改为 禁用所有交换文件

要启用内存锁定,请在 elasticsearch.yml 中将 bootstrap.memory_lock 设置为 true

bootstrap.memory_lock: true

如果 mlockall 尝试分配的内存超过可用内存,则可能会导致 JVM 或 shell 会话退出!

启动 Elasticsearch 后,您可以通过检查此请求输出中 mlockall 的值来查看此设置是否已成功应用

resp = client.nodes.info(
    filter_path="**.mlockall",
)
print(resp)
response = client.nodes.info(
  filter_path: '**.mlockall'
)
puts response
GET _nodes?filter_path=**.mlockall

如果您看到 mlockallfalse,则表示 mlockall 请求已失败。您还将在日志中看到一行包含 无法锁定 JVM 内存 字样的更多信息。

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

.zip.tar.gz

在启动 Elasticsearch 之前,以 root 用户身份设置 ulimit -l unlimited。或者,在 /etc/security/limits.conf 中将 memlock 设置为 unlimited

# allow user 'elasticsearch' mlockall
elasticsearch soft memlock unlimited
elasticsearch hard memlock unlimited
RPM 和 Debian
systemd 配置 中将 LimitMEMLOCK 设置为 infinity

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

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

或在 jvm.options 配置文件中设置此 JVM 标志。