作者:来自 Elastic Valentin Crettaz
探索 Elasticsearch 的内存需求以及不同类型的内存统计信息。
Elasticsearch 拥有丰富的新功能,帮助你为你的使用场景构建最佳搜索解决方案。浏览我们的示例笔记本了解更多信息,开始免费云试用,或者现在就在本地机器上体验 Elastic。
Elasticsearch 的内存需求
Elasticsearch 进程对内存的需求非常高。Elasticsearch 使用 JVM(Java Virtual Machine),最佳实践建议为 JVM 分配接近节点可用内存的 50%。JVM 依赖内存,以便 Lucene 进程能够非常快速地访问索引值。剩下的 50% 留给文件系统缓存,用来将经常访问的数据保存在内存中。
要了解 JVM 内存管理的完整解释,请阅读这篇博客。收到来自不同类型断路器(circuit breakers)的警告也是很常见的。
jvm.mem
最重要的内存部分是 JVM 堆内存。
`GET _nodes/stats/jvm`AI写代码
输出如下所示:
`
1. "jvm" : {
2. "timestamp" : 1603351829573,
3. "uptime_in_millis" : 150932107,
4. "mem" : {
5. "heap_used_in_bytes" : 258714272,
6. "heap_used_percent" : 24,
7. "heap_committed_in_bytes" : 1073741824,
8. "heap_max_in_bytes" : 1073741824,
9. "non_heap_used_in_bytes" : 192365488,
10. "non_heap_committed_in_bytes" : 209186816,
`AI写代码
请注意,健康的 JVM 中的 heap_used_in_bytes 会因为垃圾回收过程而呈现锯齿状模式,使用量会逐渐上升到大约 70%,然后在垃圾回收发生时迅速降到 30%。
JVM 的 heap_max_in_bytes 取决于 jvm.options 文件中设置的值,建议你将其设置为容器或服务器可用内存的 50%。
关于 JVM 堆内存问题的更多信息,请参阅:Elasticsearch 中的堆大小使用和 JVM 垃圾回收。
解释不同类型的内存统计信息
查看内存统计信息时,我们需要注意,许多 Elasticsearch 应用运行在容器中,而这些容器部署在更大的机器上。这在你使用 AWS Elasticsearch 服务、Elastic Cloud 这类托管服务,或是在 Docker 或 Kubernetes 上运行 Elasticsearch 时很常见。在这种情况下,解读可用的内存统计信息时需要特别小心。
Elasticsearch 监控 API 提供了多种内存统计信息,如下所述:
`
1. GET _nodes/stats/os
2. "os" : {
3. "timestamp" : 1603350306857,
4. "cpu" : {
5. "percent" : 13,
6. "load_average" : {
7. "1m" : 3.37,
8. "5m" : 3.18,
9. "15m" : 2.8
10. }
11. },
12. "mem" : {
13. "total_in_bytes" : 16703369216,
14. "free_in_bytes" : 361205760,
15. "used_in_bytes" : 16342163456,
16. "free_percent" : 2,
17. "used_percent" : 98
18. },
19. "swap" : {
20. "total_in_bytes" : 1023406080,
21. "free_in_bytes" : 1302528,
22. "used_in_bytes" : 1022103552
23. },
24. "cgroup" : {
25. "cpuacct" : {
26. "control_group" : "/",
27. "usage_nanos" : 2669636420088
28. },
29. "cpu" : {
30. "control_group" : "/",
31. "cfs_period_micros" : 100000,
32. "cfs_quota_micros" : -1,
33. "stat" : {
34. "number_of_elapsed_periods" : 0,
35. "number_of_times_throttled" : 0,
36. "time_throttled_nanos" : 0
37. }
38. },
39. "memory" : {
40. "control_group" : "/",
41. "limit_in_bytes" : "9223372036854771712",
42. "usage_in_bytes" : "4525641728"
43. }
44. }
45. }
`AI写代码
上述统计信息是针对在 Docker 上运行的开发节点。让我们解释一下我们收到的各个部分:
os.mem
第一个部分 “os.mem” 指的是运行该机器的主机。在这种情况下,我们运行在 Docker 上,因此 16GB 指的是容器所在主机的内存。请注意,机器使用接近 100% 的内存是完全正常的,这并不表示有问题。
os.swap
“os.swap” 部分同样指的是主机。在这种情况下,我们可以看到主机允许交换。当我们在启用交换的主机内运行容器时,这是很正常的。如果要确认 Docker 容器内是否禁止交换,可以通过运行以下命令进行检查:
`GET _nodes?filter_path=**.mlockall`AI写代码
os.cgroup
最后,我们可以看到 “os.cgroup” 部分,它指的是容器本身。在这种情况下,容器使用了 4GB 的内存。
process.mem
我们还可以访问一个虚拟内存的统计信息:
`
1. GET _nodes/stats/process
2. "process" : {
3. "timestamp" : 1603352751181,
4. "open_file_descriptors" : 436,
5. "max_file_descriptors" : 1048576,
6. "cpu" : {
7. "percent" : 0,
8. "total_in_millis" : 1964850
9. },
10. "mem" : {
11. "total_virtual_in_bytes" : 5035376640
12. }
`AI写代码
注意,“process.total_virtual_in_bytes” 包括了进程可用的整个内存,包括通过 mmap 获得的虚拟内存。