如何避免物理磁盘 I/O

Posted

技术标签:

【中文标题】如何避免物理磁盘 I/O【英文标题】:How to avoid physical disk I/O 【发布时间】:2011-11-01 20:31:04 【问题描述】:

我有一个通过网络写入大量数据的进程。假设它在机器 A 上运行,并通过 NFS 在机器 B 上转储大约 70-80GB 的文件。进程 1 完成并退出后,我的进程 2 运行机器 A 并通过 NFS 从机器 B 获取此文件。整个周期的瓶颈就是这个庞大的数据文件的读写。我怎样才能减少这个 输入/输出时间?我能否以某种方式将数据加载到内存中,以便在进程 1 退出后也可供进程 2 使用?

我很感激这方面的想法。谢谢。

编辑:由于进程 2 直接从网络“读取”数据,是否会更好 先本地复制数据,再从本地磁盘读取? 我的意思是 (网络读取时间) > (cp 到本地磁盘) + (从本地磁盘读取)

【问题讨论】:

为什么不将文件保存在机器 A 上? 你能将数据直接从进程 1 传送到进程 2 吗? 【参考方案1】:

如果您想将数据加载到内存中,则需要 70-80 GB 的 RAM。

最好的办法是在系统 A 上附加一个本地存储(硬盘驱动器)以将该文件保存在本地。

【讨论】:

【参考方案2】:

显而易见的答案是减少网络写入 - 这似乎可以成倍地节省您的时间并提高可靠性 - 将 any 文件复制到另一台机器只是为了将其复制回来似乎没有什么意义,因此为了更准确地回答您的问题,我们需要更多信息。

【讨论】:

【参考方案3】:

这种方法有很多网络和 IO 开销。因此,您可能无法进一步降低延迟。

    由于文件超过 80 GB,创建一个进程 1 将写入的 mmap,稍后进程 2 可以从中读取 - 不涉及网络,仅使用机器 A - 但仍有 IO 开销是不可避免的。 更快:两个进程可以同时运行,您可以使用信号量或其他信号机制,其中进程 1 可以指示进程 2 文件已准备好读取。 最快的方法:让进程 1 创建一个共享内存并与进程 2 共享。每当达到限制(可以加载到内存中的最大数据块,取决于您的 RAM 大小)时,让进程 1 向进程 2 发出信号可以读取和处理数据 - 只有当文件/数据实际上可以逐块处理而不是 80GB 的一大块时,此解决方案才可行。

【讨论】:

共享内存大小有上限。我认为默认值为 32MB。有什么方法可以通过我的应用程序增加它? 您可以通过ipcs -l查看限制,您可以通过/etc/sysctl.conf更改限制。设置kernel.shmmax=<value> 并执行sysctl -p。您只能以 root 身份执行此操作。虽然_sysctl() 可以从您的应用程序中实现此功能,但不推荐使用此功能。【参考方案4】:

无论你使用mmap 还是普通的read/write 应该没什么区别;无论哪种方式,一切都通过文件系统缓存/缓冲区发生。最大的问题是 NFS。提高效率的唯一方法是将中间数据本地存储在机器 A 上,而不是通过网络将其发送到机器 B,然后再将其拉回。

【讨论】:

这是一个很好的观点。有可以用作本地存储的安全挂载吗?我可能在“cwd”中没有写权限..【参考方案5】:

使用tmpfs 将内存用作(临时)文件。

使用mbuffer 和netcat 可以简单地从一个端口中继到另一个端口,而不存储中间流,但仍允许流以不同的速度发生:

machine1:8001 -> machine2:8002 -> machine3:8003

在 machine2 上配置如下作业:

 netcat -l -p 8002 | mbuffer -m 2G | netcat machine3 8003

这将允许最多缓冲 2 gig 的数据。如果缓冲区填满 100%,则 machine2 将开始阻塞来自 machine1 的读取,从而延迟输出流而不会失败。

当 machine1 完成传输后,第二个 netcat 将一直存在,直到 mbuffer 耗尽

【讨论】:

【参考方案6】:
    您可以使用 RAM 磁盘作为存储空间 NFS 很慢。尝试使用其他方式将数据传输到另一台 PC。示例 - TCP/IP 流。 另一种解决方案 - 您可以使用内存数据库(示例为 TimesTen)

【讨论】:

以上是关于如何避免物理磁盘 I/O的主要内容,如果未能解决你的问题,请参考以下文章

条带化

数据库优化 -索引-避免全表扫描

磁盘I/O性能优化的几个思路

Linux LVM条带化

linux性能优化磁盘I/O性能优化思路

RAID各种级别及特性