监控系统不断警告我的机器正在达到/突破其 RAM 使用阈值,即15 GB。
我读过一些书,了解到表面上的 RAM 利用率并不实际,额外的 RAM 用于磁盘 I/O 操作的缓存/缓冲,以提高服务器的性能。我在该服务器上运行 MySQL,这是唯一运行的值得注意的服务。
- 那么如何减少磁盘 I/O 缓存/缓冲 RAM 以免突破阈值呢?这可能是 MySQL 的问题而不是 Linux 的问题吗?
这就是输出free -gt
[root@ipk ~]# free -gt
total used free shared buffers cached
Mem: 15 15 0 0 0 9
-/+ buffers/cache: 5 10
Swap: 5 0 5
Total: 21 15 6
Linux 版本是:
[root@ipk ~]# uname -rmo
2.6.32-220.el6.x86_64 x86_64 GNU/Linux
答案1
由于你似乎既不接受我们的意见,也不接受我们链接到的各种页面作为“官方”,也许官方的 Red Hat文档会说服你:
在此示例中,可用内存总量为 4040360 KB。 264224 KB 供进程使用,3776136 KB 可供其他应用程序使用。不要对显示 28160KB 可用的第一行感到困惑!如果查看使用数据,您会发现大部分内存使用用于缓冲区和缓存。Linux 总是尝试使用 RAM 来加速磁盘操作,方法是将可用内存用于缓冲区(文件系统元数据)和缓存(包含文件或块设备实际内容的页面)。这有助于系统运行得更快,因为磁盘信息已经在内存中,从而节省了 I/O 操作。如果像 Oracle 这样的程序或应用程序需要空间,那么 Linux 将释放缓冲区和缓存,为应用程序提供内存。如果您的系统运行了一段时间,您通常会在第一行的“空闲”字段下看到一个小数字。
答案2
这一切都很好,但是在必须发出内存请求和将其映射到磁盘缓存必须释放的内容之间的延迟时间又如何呢?当然,你可能会说它很小,或者甚至不明显,但也许我关心因为这个过程而增加的 0.0000001 秒。你是谁来决定我的 RAM 的使用方式?
如果我不想经历这种滞后时间怎么办?也许我不介意我的应用程序从驱动器加载速度较慢,但希望它立即占用 RAM,而不会产生从磁盘缓存取消映射内存的延迟时间。
如何限制磁盘缓存占用的 RAM 量?不要告诉我这是没有办法实现的。
更新: 找到办法了。
echo 3 | sudo tee /proc/sys/vm/drop_caches
执行a:free -m
运行上面确认后。有用。
答案3
您知道您的监控真正使用哪些指标吗?对于现代 Linux 内核,您基本上应该遵循MemAvailable
:
$ grep MemAvailable: /proc/meminfo
MemAvailable: 11747552 kB
因为除非你真正知道自己在做什么,否则 Free、Cache 和 Buffers 真的没有任何意义。缓冲区和高速缓存是同一件事,并且包括所有共享内存。例如,如果您运行 PostgreSQL 并将其shared_buffers
值配置为 10 GB,您的缓冲区/缓存值将增加 10 GB,并且该内存不能使用由内核处理其他任何事情。任何说你可以直接添加Free
并添加Cache
到其中的人,都是在谈论历史系统或一些特殊情况,在这些情况下,如果需要,所有缓存确实可以删除。
现代内核正是出于这个原因计算可用内存。如果内核版本和free
可执行文件都足够新,则输出应该看起来更像这样
$ free -m
total used free shared buff/cache available
Mem: 31807 6161 5097 970 20547 11471
Swap: 1590 51 1538
请注意最后一列available
。这就是你应该关注的价值。请注意,上面的示例显示 5 GB 可用空间和 20 GB 缓存 - 对于一般情况,请忽略这些。如果我要运行一个突然需要 15 GB RAM 的程序,我会假设 OOM Killer 采取行动而不是缓存被丢弃。
根据我的经验,一旦“可用”变为零,系统可能仍然可以正常响应,但据内核所知,系统无法在没有高风险的情况下应对任何更多的负载,从而降低速度。
另一个有意义的值是Committed_AS
.一旦超过你的实际 RAM,系统可能会耗尽内存,但实际结果取决于你运行的程序 - 如果你运行调用fork()
但不弄脏内存的大程序,你可能会没事,感谢 Linux 内存管理的 CoW 功能。例如,
$ grep -E 'MemTotal:|Committed_AS:' /proc/meminfo
MemTotal: 32570620 kB
Committed_AS: 20839784 kB
对于这个例子,MemTotal
负值Committed_AS
恰好接近,MemAvailable
但这是不可信的。对于我通常的工作负载,OOM Killer 通常会在Committed_AS
达到大约 130%MemTotal
或更高的时间开始杀死应用程序。当然,如果添加大量交换,OOM Killer将不会激活,但系统会因交换而变慢。