Linux 数据移动器的 I/O 瓶颈

Linux 数据移动器的 I/O 瓶颈

我有一台 24 核机器,内存为 94.6GiB,运行 Ubuntu 服务器 10.04。这台机器的 %iowait 很高,与我们拥有的另一台运行相同类型和数量进程的服务器(4 核)不同。两台机器都连接到 VNX Raid 文件服务器,24 核机器通过 4 个 FC 卡,另一台通过 2 个千兆以太网卡。4 核机器目前性能优于 24 核机器,CPU 使用率更高,%iowait 更低。

在 9 天的正常运行时间内,%iowait 平均为 16%,并且经常超过 30%。大多数时候 CPU 使用率非常低,约为 5%(由于 iowait 较高)。有充足的可用内存。

我不明白的一件事是为什么所有数据似乎都经过设备 sdc,而不是直接经过数据移动器:

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           6.11    0.39    0.75   16.01    0.00   76.74

Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn
sda               0.00         0.00         0.00       1232          0
sdb               0.00         0.00         0.00       2960          0
sdc               1.53        43.71        44.54   36726612   37425026
dm-0              0.43        27.69         0.32   23269498     268696
dm-1              1.00         1.86         7.74    1566234    6500432
dm-2              0.96         1.72         5.97    1442482    5014376
dm-3              0.49         9.57         0.18    8040490     153272
dm-4              0.00         0.00         0.00       1794         24
dm-5              0.00         0.00         0.00        296          0

另一个难题是,任务经常进入不可中断的睡眠模式(在顶部),这也可能是由于 io 延迟造成的。

我可以查看什么来帮助诊断问题?为什么所有数据都经过 /dev/sdc?这正常吗?

更新:

网络连接和 VNX 读写容量已不再是瓶颈。使用 4 个绑定 NIC(循环),我们可以达到 800MB/s 的速度。光纤通道卡尚未使用。VNX 能够很好地处理 IO(RAID6,两个池中每个池 30x2TB 7.2kRPM 磁盘(总共 60 个磁盘),读取率约为 60%)。

忽略上面关于 dm 和 sdc 的内容,它们都是内部磁盘,而不是问题的一部分。

我们认为问题可能出在 nfs 挂载或 TCP 上(我们在 VNX 上有 5 个分区的 5 个挂载),但不知道具体是什么。有什么建议吗?

答案1

首先,如果您的 CPU(该死!有 24 个)处理数据的速度比提供数据存储的速度快,那么您就会遇到 iowait。这是内核在阻塞 io(读取速度太慢或同步写入)期间暂停进程的情况。
因此请检查存储是否可以为 24 个内核提供足够的吞吐量。

例如,假设您的存储可以提供 500MB/s 的吞吐量,并且您通过 2 千兆以太网线路 (bond) 连接,网络已经将最大吞吐量限制在 100-180 MB/s 左右。如果您的进程以 50 MB/s 的速度消耗数据,并且您在 4 核机器上运行 4 个线程:4 x 50 MB/s = 200 MB/s 消耗。如果网络可以维持 180MB/s,那么您将不会有太多延迟,并且您的 CPU 将满负荷。这里的网络是一个小瓶颈。
现在,如果您将其扩展到 24 个核心和 24 个线程,您将需要 1200 MB/s,即使您更改线路以允许这样的吞吐量,您的存储系统也不会提供超过 500 MB/s 的速度,它就会成为瓶颈。

说到 io 等待,瓶颈无处不在。不仅在物理层,而且在软件和内核空间缓冲区中。这实际上取决于使用模式。但由于软件瓶颈更难识别,因此通常最好在调查软件堆栈之前检查硬件上的理论吞吐量。

如上所述,当进程执行读取操作并且数据需要时间才能到达时,或者当进程执行同步写入操作并且数据修改确认需要时间时,就会发生 iowait。在同步写入期间,进程进入不间断睡眠状态,这样数据就不会被破坏。有一个方便的工具可以查看哪个调用导致进程挂起:latencytop。它不是唯一的一个,但你可以试一试。

注意:供您参考,dm 代表设备映射器而不是数据移动器。

答案2

首先,天哪,这可有好多铁啊!:)

不幸的是,由于您的设置听起来非常复杂,我认为没有人能够直接给出“这就是您的问题!”的答案,除非他们使用极其相似或相同的设置做过某事并遇到了同样的问题。因此,虽然 SU 将这段文字标记为“答案”,但您可能应该将其视为“建议”。我无法将其放在评论中,因为它的字数太多了。:S

如果不知道硬件如何映射到设备,就很难说清楚为什么 I/O 会转到一个地方而不是另一个地方。您是如何安装设备的?您的程序是否sd*直接访问设备,还是所有文件系统都安装在设备上dm并且所有文件访问都通过那里进行?

我还想问一下其他事情:

  • 这是哪种 RAID?如果您使用 RAID5 或 RAID6 计算奇偶校验位,则希望由 RAID 服务器硬件来处理...如果不是,则由处理服务器来处理....这不是最理想的,如果在软件中完成,可能会导致 I/O 延迟。

  • 您在邮件中指出了两台服务器之间的主要区别之一。一台使用光纤通道,另一台使用以太网。光纤通道应该提供更好的延迟和带宽,但这也许也是一个问题:如果它提供大量的吞吐量,它可能会使 RAID 服务器本身非常繁忙……并且拥塞导致缓冲区/缓存填满,从而增加延迟,导致更高的 I/O 等待。

就好像你可能磁盘阵列存在缓冲区膨胀问题 - 您知道吗?硬件 RAID 控制器通常有大量板载缓存,不是吗?因此,随着介质的 I/O 排队,缓存中充满了脏页,最终整个系统会饱和(如果机械存储无法跟上负载),延迟会急剧上升……使用 24 核 + FC 肯定比使用 4 核 + GbE 产生更多的负载 :) 检查 RAID 服务器,看看磁盘有多忙……很多“I/O”可能只是控制数据包等。我不确定 FC 如何工作,但如果它与 TCP 类似,那么如果延迟太高,您将看到重新传输。

比如,如果你在电话里问别人一个问题,而对方几秒钟都没有回答,你会说“你好?”——网络协议(FC 只是一种网络协议)也会做同样的事情,只是时间更短。但当然,在网络环境中,额外的“你好?”代价是昂贵的,因为它会给已经拥堵的管道添加更多数据。

最后,给大家一个总体建议:

在调试延迟/IO 等待/吞吐量问题时,始终措施. 处处测量。测量线路、测量程序本身正在做什么、测量处理端、测量 RAID 服务器等。不要只从一个角度看待它——尝试考虑负责处理、读取或写入管道中任何数据的系统的每个单独组件。拆开一个事务或一个离散工作单元,精确剖析它通过硬件所采用的路径,并测量每个不同组件,以查看是否存在瓶颈或存在过度延迟的地方等。我的一个朋友将此称为“剥洋葱”,从那时起,我就一直用这个短语来指代调试数据流的任务。

答案3

一个小补充。在这种情况下,您可能需要查看块级调优和 I/O 调度程序。我不太熟悉 Ubuntu,但有很多存储性能旋钮可以调整。这绝对适用于 SAN 存储和数据库的情况。

  • 看看系统输入/输出调度程序CFQ是默认设置,但是无操作最后期限是数据库工作负载的常见选择。
  • 此链接一些其他可能有帮助的调整参数。
  • 您提到了 NFS 和块存储。如果是块存储,正在使用哪些文件系统?从这里看来,I/O 等待听起来像是写入阻塞的情况。是否启用了写入屏障?使用 重新挂载文件系统nobarrier。(Ubuntu 提示

一些相关的服务器故障链接...

Linux - 实际硬件 RAID 控制器调整(scsi 和 cciss)

答案4

我很快就会编辑更多信息,但首先我想说的是,您不应该让 iostat 的 dm-* 输出让您感到困惑。Device-mapper 是一个内核直通设备,就像 md*(md0、md1 等)一样,因此您实际上只关心底层设备。传递到磁盘的所有数据都会在途中经过 dm/md,实际总数(字节、秒等)是准确的,但实用程序具有误导性。

而且,这是非常大的内存量。当内存量这么大时,就会出现一些奇怪的事情(我自己运行的是 2x64 和 2x96),特别是当一个进程占用了超过一半的内存时。阅读本文了解更多信息。文章提到了mysql,但请注意,它是不是mysql 特定。每个软件进程都会因访问另一个物理处理器的内存而受到惩罚 - 假设 48gb 属于一个进程,48gb 属于另一个进程。进程只能属于一个进程,为了访问其他进程的内存(在其自己的 48GB 用完之后),它必须决定是将其 48GB 中的一些存储在交换中,还是付出巨大的代价来访问和离开其他进程的内存。本文建议运行 numactl 命令来强制软件不进行交换,而是付出惩罚。我个人看到了由此带来的大量改进。换句话说 - 检查您的一些 I/O 是否要进行交换!为此使用 free -m(或类似命令)。如果您有足够的可用内存,但交换量不小(比如 10% 以上),这很可能就是您的问题。

相关内容