在两台计算机之间发送大量数据的最快方法是什么?

在两台计算机之间发送大量数据的最快方法是什么?

这是我经常遇到的情况:

  • 我有一个源服务器,里面有 320GB 硬盘和 16GB 内存(确切的规格可以在这里找到,但由于这是我在其他机器上也经常遇到的问题,我希望答案可以在任何“合理”的 Linux 机器上工作)
  • 我有一个备份服务器,有几 TB 的硬盘空间(确切的规格在这里,请参阅上面的免责声明)

我想将 320GB 的数据从源服务器传输到目标服务器(具体来说,来自 的数据/dev/sda)。

  1. 两台计算机物理上相邻,因此我可以在它们之间布线。
  2. 我在局域网上,并且我正在使用一个新的路由器,这意味着我的网络速度“理想”应该是 1000Mbit,对吧?
  3. 安全不是问题。我在本地网络上,并且我信任全部网络上的机器,包括路由器。
  4. (选修的)我不一定需要数据的签名校验和,但应该检测基本的错误检查(例如丢失的数据包或驱动器变得不可读),而不是仅仅消失在输出中。

我在网上搜索了这个问题,并测试了几个命令。最常出现的就是这个:

ssh [email protected] 'dd bs=16M if=/dev/sda | gzip' > backup_sda.gz

事实证明,这个命令太慢了(它运行了一个小时,只获取了大约 80GB 的数据)。 1GB 测试包大约需要 1 分 22 秒,未压缩时速度是原来的两倍。由于传输的文件小于源系统上的 RAM 量,结果也可能会出现偏差。

此外(这是在 1GB 测试件上进行测试的),如果我使用命令gzipand ,我会遇到问题dd;在目标上提取时生成的文件与直接通过管道传输时相比具有不同的校验和。我仍在试图找出为什么会发生这种情况。

答案1

由于服务器在物理上彼此相邻,并且您在评论中提到您可以物理访问它们,因此最快的方法是将硬盘从第一台计算机中取出,放入第二台计算机中,然后通过 SATA 连接传输文件。

答案2

netcat对于安全不成问题的情况来说非常有用:

# on destination machine, create listener on port 9999
nc -l 9999 > /path/to/outfile

# on source machine, send to destination:9999
nc destination_host_or_ip 9999 < /dev/sda
# or dd if=/dev/sda | nc destination_host_or_ip 9999

请注意,如果您使用ddGNU coreutils,您可以发送SIGUSR1到进程,它会将进度发送到 stderr。对于 BSD dd,请使用SIGINFO.

光伏发电在复制过程中报告进度甚至更有帮助:

# on destination
nc -l 9999 | pv > /path/to/outfile

# on source
pv /dev/sda | nc destination_host_or_ip 9999
# or dd if=/dev/sda | pv | nc destination_host_or_ip 9999

答案3

  1. 使用快速地压缩。

    • 无论您使用哪种传输介质(尤其是网络或 USB),您都将使用数据爆发用于读取、缓存和写入,并且这些不会完全同步。
    • 除了磁盘固件、磁盘缓存和内核/RAM 缓存之外,如果您还可以以某种方式使用系统的 CPU 来集中每个磁盘交换的数据量。爆裂然后你应该这样做
    • 任何压缩算法都会尽可能快地自动处理稀疏的输入运行,但很少有算法能够以网络吞吐量处理其余部分。
    • lz4是你最好的选择:

      LZ4 是一种非常快的无损压缩算法,提供每核 400 MB/s 的压缩速度,可通过多核 CPU 进行扩展。它还具有极快的解码器,每个核心的速度为数 GB/秒,通常达到多核系统上的 RAM 速度限制。

  2. 最好做不是不必要地寻求。

    • 这可能很难衡量。
    • 如果您从中复制的设备上有大量可用空间,并且该设备最近尚未清零,但应复制所有源文件系统,那么可能值得您花时间首先执行此操作就像是:

      </dev/zero tee >empty empty1 empty2; sync; rm empty*
      
    • 但这取决于您应该阅读源代码的级别。通常需要从头到尾读取设备/dev/some_disk设备文件,因为在文件系统级别读取通常涉及非顺序地在磁盘上来回查找。所以你的读取命令应该是这样的:

      </dev/source_device lz4 | ...
      
    • 但是,如果您的源文件系统不应该被整个传输,那么在文件系统级别的读取是不可避免的,因此您应该将输入内容集中到一个流中。pax在这种情况下通常是最好和最简单的解决方案,但您也可以考虑mksquashfs

      pax -r /source/tree[12] | lz4 | ...
      mksquashfs /source/tree[12] /dev/fd/1 -comp lz4 | ...
      
  3. 不是加密与ssh.

    • 向可信介质添加加密开销是不必要的,并且可能会严重损害传输速度持续传输中读取的数据需要读取两次
    • PRNG需要读取数据,或者至少是其中的一些数据,以维持随机性。
    • 当然,您还需要传输数据。
    • 您还需要传输加密开销本身 - 这意味着传输的数据更少,工作量更大每次突发
    • 所以你应该使用netcat(或者,如我所愿,nmap项目能力更强ncat)用于简单的网络副本,正如其他地方所建议的那样:

      ###  on tgt machine...
      nc -l 9999 > out.lz4
      ###  then on src machine...
      ... lz4 | nc tgt.local 9999
      

答案4

我们定期处理这个问题。

我们倾向于使用的两种主要方法是:

  1. SATA/eSATA/运动鞋网
  2. 直接 NFS 挂载,然后本地cprsync

第一个取决于驱动器是否可以物理重新定位。这并非总是如此。

第二个效果出奇的好。一般来说,我们可以通过直接 NFS 安装轻松地达到 1gbps 连接的最大值。使用 scp、dd over ssh 或任何类似的方法都无法达到这个目标(您经常会得到可疑地接近 100mpbs 的最大速率)。即使在非常快的多核处理器上,您也会遇到两台机器中最慢的一个核心的最大加密吞吐量的瓶颈,这与未加密网络安装上的全口径 cp 或 rsync 相比慢得令人沮丧。有时,您会遇到一段时间的 iops 墙,并卡在约 53MB/s 左右,而不是更典型的约 110MB/s,但这通常是短暂的,除非源或目标是实际上一个驱动器,那么你可能最终会受到驱动器本身持续速率的限制(由于随机原因,在你实际尝试之前你不会知道它的变化很大)——嗯。

如果 NFS 在一个不熟悉的发行版上,设置起来可能有点烦人,但一般来说,它是尽可能完全填充管道的最快方法。上次我以超过 10gbps 的速度执行此操作时,我实际上从未发现它是否已达到最大连接,因为在我喝完咖啡回来之前传输就结束了 - 所以您可能会遇到一些自然限制。如果源和目标之间有一些网络设备,则可能会因网络链接效应而遇到一些轻微的延迟或中断,但通常这可以在整个办公室(没有其他流量搞砸)或从数据中心的一端到另一个(除非你在内部进行某种过滤/检查,在这种情况下,所有的赌注都失败了)。

编辑

我注意到一些关于压缩的讨论......不是压缩连接。它会像加密层一样减慢你的速度。如果您压缩连接,瓶颈将始终是单个核心(并且您甚至不会获得该核心总线的特别好的利用率)。在您的情况下,您能做的最慢的事情是在两台相邻计算机之间使用 1gbps 或更高连接速度的加密、压缩通道。

面向未来

该建议自 2015 年中期起生效。这几乎将当然未来很多年都不会出现这种情况。因此,凡事都要持保留态度,如果您经常面临这项任务,那么请尝试各种方法实际负载不要想象你会得到任何接近理论最佳值的东西,甚至观察到网络流量等典型的压缩/加密吞吐量,很多其中是文本的(提示:批量传输通常主要由图像、音频、视频、数据库文件、二进制代码、办公文件格式等组成。已经压缩了以他们自己的方式,并且通过另一个压缩例程运行几乎没有什么好处,该例程的压缩块大小几乎可以保证与已经压缩的二进制数据不对齐......)。

我想未来像 SCTP 这样的概念将被带到一个更有趣的地方,其中绑定连接(或内部按频谱绑定通道化光纤连接)是典型的,每个通道都可以接收独立于其他通道的流,并且每个通道都可以接收流。流可以并行压缩/加密等等。那太好了!但 2015 年的情况并非如此,尽管幻想和理论化都很好,但我们大多数人都没有在冷冻室中运行自定义存储集群,将数据直接输入 Blue Gene/Q 的内部,为 Watson 生成答案。那不是现实。我们也没有时间彻底分析我们的数据有效负载来确定压缩是否是一个好主意——在我们完成分析之前,传输本身就会结束,无论选择的方法有多糟糕。

但...

时代变迁我反对压缩和加密的建议是站不住脚的。我真的希望这个建议能够被推翻典型很快。这会让我的生活更轻松。

相关内容