我遇到了 Linux 页面缓存的严重问题,它减慢了 IO 速度。例如,如果我使用 dd 复制 lvm 分区,Linux 会将数据缓存在缓冲区或缓存中(free –m)。这不是问题,但在缓冲区达到特定值后,复制过程会停止并减慢到几 mbs 甚至几 kbs。我已经对写入磁盘或 /dev/null 进行了许多测试,问题与源驱动器或目标驱动器无关。
详细地:
- 有两台几乎完全相同的服务器。两台服务器都运行 CentOS 6.5,内核相同。它们有相同的磁盘、相同的设置、相同的其他硬件,所有方面都相同。唯一的区别是一台服务器有 2 个 CPU 和 64GB 内存,另一台有 1 个 CPU 和 32GB 内存。
- 这也是以下复制过程的图像:https://i.stack.imgur.com/tYlym.jpg
- 这里是带有 meminfo 的新版本。meminfo 来自不同的运行,因此值不相同,但其行为完全相同:https://i.stack.imgur.com/4SIJG.jpg
- 使用 dd 或其他文件系统复制程序开始复制。
- 缓冲区或缓存开始填充。一切正常。
- 缓冲区或缓存达到最大数量(在 64GB RAM 服务器上,该值类似于 32GB 或 17GB;在 32GB RAM 服务器上,所有可用内存)
- 在 64GB RAM 服务器上,复制过程现在停止或限制为几 MB。在 32GB RAM 服务器上一切正常。
- 在 64GB RAM 服务器上,我可以通过强制使用“sync; echo 3 > /proc/sys/vm/drop_caches”来暂时解决问题。但当然,缓冲区会立即再次开始增长,问题再次出现。
结论:
问题要么与第二个 CPU 有关,要么与总内存量有关。我“感觉”问题可能是,每个 CPU 都有自己的 32GB RAM,而复制过程仅在 CPU 上运行。因此,最终复制过程将缓冲区/缓存增加到接近 32GB 或另一个 CPU 未使用的内存,然后 Linux 认为还有内存,所以让我们进一步增加缓冲区,但下面的硬件无法访问内存,或类似情况。
有人有想法或解决方案吗?当然,我可以使用带有直接标志的 dd,但这并不能解决问题,因为还可以通过 samba 等进行外部访问。
编辑1:
这里还有来自 64GB RAM 服务器的 /proc/zoneinfo:1.http://pastebin.com/uSnpQbeD(dd 开始之前)2.http://pastebin.com/18YVTfdb(当 dd 停止工作时)
编辑2:
- 虚拟机设置:http://pastebin.com/U9E9KkFS
- /proc/sys/vm/zone_reclaim_mode 在 32 GB ram 服务器 0 和 64 GB ram 服务器 1 上。我从未触碰过这些值。安装程序设置了这些值。我暂时将其更改为 0 并重试测试。现在所有内存都用于缓冲区和缓存。所以它看起来很棒,就像其他服务器一样。但随后它立即开始全速交换...我将 swapiness 设置为 0。这有帮助,但它仍然每秒交换几 MB。并且它每秒增加缓冲区。所以它不交换缓冲区,它交换 vms 的内存以获得更多内存来增加缓冲区...疯了。但也许这是正常的!?
编辑3:
/proc/buddyinfo 和 numactl --hardware: http://pastebin.com/0PmXxxin
最后结果
- /proc/sys/vm/zone_reclaim_mode 肯定是技术上的正确方法,但之后机器就不能很好地工作了。例如:如果我复制磁盘,linux 现在会使用 100% 的可用内存进行缓冲(而不是像以前那样只使用 XGB 然后停止)。但在最后一块可用内存用于缓冲时,linux 开始交换 vm 内存并增加缓冲区和缓存的总量。我的系统通常不需要交换,因此交换内存与某些 vm 位于同一磁盘上。结果是,如果备份这些 vm,linux 会在我从磁盘读取备份的同时写入交换。因此,交换 vm 很糟糕,但更糟糕的是 linux 破坏了我的备份读取速度……因此将 /proc/sys/vm/zone_reclaim_mode 设置为 0 并不能解决整个问题……目前我在屏幕上运行一个脚本,该脚本每 10 秒同步和刷新缓存一次……虽然不太好,但对我来说效果要好得多。我的系统上没有 Web 服务器或普通文件服务器。我只运行 vms、进行备份并通过 samba 存储备份。我不喜欢这个解决方案。
答案1
您看到的行为是由于 Linux 在 NUMA 系统上分配内存的方式造成的。
我假设(但不知道)32GB 系统是非 Numa 的,或者 Numa 不足以让 Linux 关心。
如何处理 numa 的行为由选项决定/proc/sys/vm/zone_reclaim_mode
。默认情况下,linux 将检测您是否正在使用 numa 系统,并在认为可以提供更好的性能时更改回收标志。
内存被分成多个区域,在 numa 系统中,第一个 CPU 插槽有一个区域,第二个 CPU 插槽有一个区域。它们显示为node0
和node1
。如果您 cat ,就可以看到它们/proc/buddyinfo
。
当区域回收模式设置为 1 时,从第一个 CPU 插槽分配将导致在与该 CPU 关联的内存区域上进行回收,这是因为从本地 numa 节点回收在性能方面更高效。从这个意义上讲,回收是删除页面(例如清除缓存)或在该节点上交换内容。
如果将值设置为 0,则当区域已满时不会发生回收,而是将内存分配到外部 numa 区域。这样做的代价是另一个 CPU 短暂锁定以获得对该内存区域的独占访问权。
但随后它立即开始交换!几秒钟后:内存:总计 66004536k,已使用 65733796k,可用 270740k,缓冲区 34250384k 交换:总计 10239992k,已使用 1178820k,可用 9061172k,缓存 91388k
交换行为和何时交换取决于几个因素,其中一个因素是分配给应用程序的页面有多活跃。如果它们不太活跃,它们将被交换以支持缓存中更繁忙的工作。我假设虚拟机中的页面不会经常被激活。