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

IQA*_*eas 117 networking backup file-transfer dd

这是我经常遇到的情况:

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

我想将 320GB 的数据从源服务器传输到目标服务器(特别是来自 的数据/dev/sda)。

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

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

ssh user@192.168.1.100 'dd bs=16M if=/dev/sda | gzip' > backup_sda.gz
Run Code Online (Sandbox Code Playgroud)

这个命令被证明太慢了(它运行了一个小时,只得到了大约 80GB 的数据)。1GB 的测试数据包大约需要 1 分 22 秒,最终在未压缩时速度是原来的两倍。结果也可能因传输的文件小于源系统上的 RAM 量而产生偏差。

此外(这是在 1GB 测试片上测试的),如果我使用gzip命令和dd; 与直接通过管道传输相比,在目标上提取的结果文件具有不同的校验和。我仍在试图弄清楚为什么会发生这种情况。

Blu*_*eft 140

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

  • +1:通过物理传输似乎是最快的途径,即使这意味着从某个地方获得一个大的外部硬盘驱动器。大约是 40 英镑,你可能已经花那么多时间了, (15认同)
  • “永远不要低估一辆装满硬盘的卡车的带宽。虽然延迟很糟糕” (10认同)
  • 如果一个人在千兆网络上获得全速,我完全不同意这个想法。在 HP Gen 7 微服务器和 Pentium G630 机器之间的 Zyxel 千兆交换机上通过 NFS/SMB 进行测试,传输速度约为 100MB/s。(直到我离开驱动器盘片的外边缘。)所以我认为这实际上可以在 3 小时内完成。除非您使用 SSD 或极高性能的驱动器/存储,否则我认为 2 个副本不能产生 100MB/s 的吞吐量,这需要每个复制操作达到 200MB/s 才能收支平衡。 (3认同)
  • @Phizes:显然您不会复制到临时文件。那是deword的坏主意,不是其他人都在谈论的。将源驱动器连接到目标机器的要点是使用 `dd`(或文件系统树副本)转到 SATA->SATA。 (3认同)
  • @Kevin:是的,我的观点是在同一台计算机中的磁盘之间直接复制至少与任何其他可能的方法一样快。我提出了现实生活中的带宽数字来承认 Phize 的观点,即通过 gigE 对 OP 旧驱动器来说很好,但对新驱动器来说却是一个瓶颈。(在一台计算机中的两个驱动器 * 不是* 最佳选择的一种情况是,当让单独的计算机使用它们的 RAM 来缓存源和目标的元数据时,这很重要,例如对于数十亿个文件的 rsync。) (3认同)

zac*_*kse 72

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
Run Code Online (Sandbox Code Playgroud)

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

pv更有助于在复制期间报告进度:

# 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
Run Code Online (Sandbox Code Playgroud)

  • 不要忘记在`bash`中可以使用`&gt; /dev/tcp/` *IP* `/` *port* 和`&lt; /dev/tcp/` *IP* `/` *port* 重定向而不是分别通过管道传入和传出 netcat。 (17认同)
  • @user1794469 压缩有帮助吗?我认为网络不是瓶颈所在。 (5认同)
  • 好答案。千兆以太网通常比硬盘驱动器速度更快,因此压缩是无用的。要传输多个文件,请考虑`tar cv sourcedir | 光伏 | nc dest_host_or_ip 9999` 和 `cd destdir ; nc -l 9999 | 光伏 | 焦油xv`。许多变化都是可能的,例如,您可能希望在目标端保留一个 `.tar.gz` 而不是副本。如果您将目录复制到目录,为了更加安全,您可以在之后执行 rsync,例如从 dest `rsync --inplace -avP user@192.168.1.100:/path/to/source/。/path/to/destination/.` 它将保证所有文件确实是精确的副本。 (5认同)
  • 除了使用 IPv4,您还可以通过使用 IPv6 获得更好的吞吐量,因为它具有更大的有效负载。你甚至不配置它,如果机器支持 IPv6,它们可能已经有一个 IPv6 链接本地地址 (3认同)
  • 对于第二个例子,`dd` 甚至是必需的,或者`pv`/`nc` 可以自己处理`/dev/sda` 吗?(我注意到一些命令在尝试读取像这样的特殊文件或带有 `0x00` 字节的文件时会“抛出”) (2认同)

mik*_*erv 36

  1. 不要使用快速压缩。

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

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

  2. 最好不要没有不必要的寻求。

    • 这可能很难衡量。
    • 如果您从中复制的设备上有很多可用空间,并且该设备最近没有被清零,但是应该复制所有源文件系统,那么您可能值得先做就像是:

      </dev/zero tee >empty empty1 empty2; sync; rm empty*
      
      Run Code Online (Sandbox Code Playgroud)
    • 但这取决于您应该阅读源代码的级别。通常希望从/dev/some_disk设备文件中从头到尾读取设备,因为在文件系统级别读取通常涉及非顺序地来回和围绕磁盘寻找。所以你的读取命令应该是这样的:

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

      pax -r /source/tree[12] | lz4 | ...
      mksquashfs /source/tree[12] /dev/fd/1 -comp lz4 | ...
      
      Run Code Online (Sandbox Code Playgroud)
  3. 不要与加密ssh

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

      ###  on tgt machine...
      nc -l 9999 > out.lz4
      ###  then on src machine...
      ... lz4 | nc tgt.local 9999
      
      Run Code Online (Sandbox Code Playgroud)


Khr*_*oph 25

有几个限制可能会限制传输速度。

  1. 1Gbps 管道上存在固有的网络开销。通常,这会将实际吞吐量降低到 900 Mbps 或更低。然后您必须记住,这是双向流量,您应该期望下降明显低于 900Mbps。

  2. 即使您使用的是“新路由器”,您确定路由器支持 1Gbps 吗?并非所有新路由器都支持 1Gbps。此外,除非它是企业级路由器,否则您可能会因为路由器效率低下而损失额外的传输带宽。虽然根据我在下面发现的内容,看起来您的速度已超过 100Mbps。

  3. 共享您的网络的其他设备可能会出现网络拥塞。您是否尝试过使用直接连接的电缆,如您所说的那样?

  4. 您使用的磁盘 IO 量是多少?很可能,您受到的限制不是网络,而是磁盘驱动器。大多数 7200rpm 的 HDD 只能达到 40MB/s 左右。你在使用raid吗?你在使用固态硬盘吗?你在远程端使用什么?

如果希望为备份重新运行,我建议使用 rsync。您还可以在另一端使用像 filezilla 这样的下载程序 scp、ftp(s) 或 http,因为它会并行化 ssh/http/https/ftp 连接。这可以增加带宽,因为其他解决方案都在单个管道上。单个管道/线程仍然受限于它是单线程的,这意味着它甚至可能受 CPU 限制。

使用 rsync,您可以消除解决方案的大量复杂性,并允许压缩、权限保留并允许部分传输。还有其他几个原因,但它通常是大型企业的首选备份方法(或运行备份系统)。Commvault 实际上在其软件下使用 rsync 作为备份的交付机制。

根据您给定的 80GB/h 示例,您的速度约为 177Mbps(22.2MB/s)。我觉得你可以在两个盒子之间的专用以太网线上使用 rsync 轻松地将其加倍,因为我已经设法在我自己的测试中使用 rsync over gigabit 来实现这一点。

  • +1 为`rsync`。_first_ 运行它可能不会更快,但它肯定会在以后的所有时间运行。 (12认同)
  • *&gt; 大多数 7200rpm HDD 只能获得大约 40MB/s。* IME 您更有可能看到使用 *现代* 驱动器(包括 ~5k 驱动器)连续超过 100MB/s。不过,这可能是较旧的磁盘。 (4认同)
  • 千兆以太网为 1000 mbps *全双工*。你得到 1000mbps(或者,正如你所说,现实中大约 900mbps)*每个方向*。其次...硬盘现在通常可以达到 100MB/秒。40MB/秒很慢,除非这是一个十年前的驱动器。 (3认同)
  • @Bob:那些现代人每分钟只能读取 5400 条圆形轨道。这些磁盘仍然很快,因为每个磁道包含超过 1 兆字节。这确实意味着它们也是相当大的磁盘,一个 320 GB 的小磁盘每个轨道不能容纳太多千字节,这必然会限制它们的速度。 (2认同)

zxq*_*xq9 18

我们会定期处理此问题。

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

  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 生成答案。那不是现实。我们也没有时间详尽地分析我们的数据有效载荷来确定压缩是否是一个好主意——传输本身将在我们完成分析之前结束,

但...

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

  • `lz4` 足够快,不会成为 gigE 的瓶颈,但根据您想对副本做什么,您可能需要未压缩它。lzop 也很快。在我的 i5-2500k Sandybridge (3.8GHz) 上,`lz4 &lt; /dev/raid0 | pv -a &gt; /dev/null` 输入为 ~180MB/s,输出为 ~105MB/s,正好适合 gigE。在接收端解压缩在 CPU 上更容易。 (2认同)
  • 我完全不同意你关于压缩的评论。这完全取决于数据的可压缩性。如果您可以获得 99.9% 的压缩率,那么不这样做将是愚蠢的——既然可以传输 100MB,为什么还要传输 100GB?我并不是建议这个问题的情况就是这种压缩级别,只是表明这必须逐案考虑,并且没有绝对的规则。 (2认同)

小智 6

我过去使用过的一个漂亮的工具是bbcp. 如此处所示:https : //www.slac.stanford.edu/~abh/bbcp/

另见http://pcbunn.cithep.caltech.edu/bbcp/using_bbcp.htm

我使用此工具的传输速度非常快。


Hop*_*nny 6

如果您以某种方式(通过电线/运动鞋网/任何方式)获得第一次通过,您可以查看rsync某些可以大大加快后续传输速度的选项。一个非常好的方法是:

rsync -varzP sourceFiles destination
Run Code Online (Sandbox Code Playgroud)

选项有:详细、存档模式、递归、压缩、部分进度

  • rsync 比 netcat 更可靠,但存档意味着递归,因此 r 是多余的。 (2认同)