未更改的大目录的更快 rsync

gue*_*tli 17 synchronization rsync

我们使用 rsync 来备份服务器。

不幸的是,某些服务器的网络速度很慢。

rsync 最多需要五分钟才能检测到大型目录中没有任何变化。这些巨大的目录树包含很多小文件(大约 80k 个文件)。

我猜 rsync 客户端会为每个 80k 文件发送数据。

由于网络很慢,我想避免发送有关每个文件的 80k 次信息。

有没有办法告诉 rsync 对子目录树进行哈希和?

这样 rsync 客户端将只为巨大的目录树发送几个字节。

更新

到目前为止,我的策略是使用rsync. 但是如果不同的工具更适合这里,我可以切换。两者(服务器和客户端)都在我的控制之下。

更新2

一棵目录树中有 80k 个文件。每个单个目录不超过 2k 个文件或子目录

更新3

有关网络缓慢的详细信息:

time ssh einswp 'cd attachments/200 && ls -lLR' >/tmp/list
real    0m2.645s
Run Code Online (Sandbox Code Playgroud)

tmp/list 文件大小:2MByte

time scp einswp:/tmp/list tmp/
real    0m2.821s
Run Code Online (Sandbox Code Playgroud)

结论:scp 速度一样(不出意外)

time scp einswp:tmp/100MB tmp/
real    1m24.049s
Run Code Online (Sandbox Code Playgroud)

速度:1.2MB/s

Tom*_*ime 38

一些不相​​关的点:

80K 是很多文件。

一个目录中有 80,000 个文件?默认情况下,没有操作系统或应用程序可以很好地处理这种情况。您只是碰巧注意到 rsync 存在这个问题。

检查您的 rsync 版本

现代 rsync 比过去更好地处理大目录。确保您使用的是最新版本。

即使是旧的 rsync 也可以通过高延迟链接很好地处理大目录……但是 80k 文件并不大……它很大!

也就是说,rsync 的内存使用量与树中的文件数成正比。大目录占用大量 RAM。缓慢可能是由于任一侧都缺少 RAM。在观察内存使用情况的同时进行测试运行。Linux 使用任何剩余的 RAM 作为磁盘缓存,因此如果您的 RAM 不足,则磁盘缓存较少。如果 RAM 用完并且系统开始使用交换,性能将非常糟糕。

确保没有使用 --checksum

--checksum(或-c) 需要读取每个文件的每个块。您可能可以使用仅读取修改时间(存储在 inode 中)的默认行为。

将作业拆分为小批量。

有一些像Gigasync这样的项目将“通过使用 perl 递归目录树来减少工作量,构建小文件列表以使用 rsync 传输。”

额外的目录扫描将是大量的开销,但也许它会是一个净赢。

操作系统默认设置不是针对这种情况。

如果你使用 Linux/FreeBSD/etc 的所有默认设置,你的所有应用程序的性能都会很糟糕。默认值假定较小的目录,以免在过大的缓存上浪费 RAM。

调整您的文件系统以更好地处理大型目录:大型文件夹是否会降低 IO 性能?

查看“namei缓存”

类似 BSD 的操作系统有一个缓存,可以加速查找 inode 的名称(“namei”缓存)。每个目录都有一个 namei 缓存。如果它太小,这不仅仅是优化的障碍。由于 rsync 正在对每个文件执行 lstat(),因此 80k 文件中的每一个都会访问 inode。这可能会破坏您的缓存。研究如何调整系统上的文件目录性能。

考虑不同的文件系统

XFS 旨在处理更大的目录。请参阅文件系统单个目录中的大量文件

也许5分钟是你能做的最好的事情。

考虑计算正在读取的磁盘块数,并计算您期望硬件能够读取那么多块的速度。

也许你的期望太高了。考虑必须读取多少磁盘块才能在不更改文件的情况下执行 rsync:每个服务器都需要读取目录并读取每个文件的一个 inode。让我们假设没有缓存任何东西,因为 80k 文件可能已经破坏了您的缓存。假设 80k 块是为了让数学保持简单。那是大约 40M 的数据,应该可以在几秒钟内读取。但是,如果需要在每个块之间进行磁盘搜索,则可能需要更长的时间。

因此,您将需要读取大约 80,000 个磁盘块。你的硬盘能做到多快?考虑到这是随机 I/O,而不是长时间的线性读取,5 分钟可能非常好。那是 1 / (80000 / 600),或者每 7.5 毫秒读取一次磁盘。你的硬盘是快还是慢?这取决于型号。

对类似的东西进行基准测试

另一种思考方式是这样的。如果没有文件更改,ls -Llr则执行相同数量的磁盘活动,但从不读取任何文件数据(仅元数据)。ls -Llr运行所需的时间是您的上限。

  • rsync(没有更改文件)是否比ls -Llr? 然后可以改进您用于 rsync 的选项。也许-c已启用或其他一些标志读取的不仅仅是目录和元数据(inode 数据)。

  • rsync(没有更改文件)几乎和 一样快ls -Llr吗?然后,您已经尽可能地调整了 rsync。您必须调整操作系统、添加 RAM、获得更快的驱动器、更改文件系统等。

与您的开发人员交谈

80k 文件只是糟糕的设计。很少有文件系统和系统工具能很好地处理如此大的目录。如果文件名是 abcdefg.txt,请考虑将它们存储在 abdc/abcdefg.txt 中(注意重复)。这会将目录分解为较小的目录,但不需要对代码进行大量更改。

另外....考虑使用数据库。如果您的目录中有 80k 个文件,那么您的开发人员可能正在解决他们真正想要的是数据库这一事实。MariaDB 或 MySQL 或 PostgreSQL 将是存储大量数据的更好选择。

嘿,5分钟有什么问题?

最后,5分钟真的那么糟糕吗?如果每天运行一次此备份,5 分钟并不是很多时间。是的,我喜欢速度。但是,如果 5 分钟对您的客户来说“足够好”,那么它对您来说就足够了。如果您没有书面 SLA,那么与您的用户进行非正式讨论以了解他们期望备份的速度如何。

如果不需要提高性能,我假设您没有问这个问题。但是,如果您的客户对 5 分钟感到满意,请宣布胜利并继续进行其他需要您努力的项目。

更新:经过一些讨论,我们确定瓶颈是网络。在我放弃之前,我将推荐两件事:-)。

  • 尝试通过压缩从管道中挤出更多带宽。然而压缩需要更多的 CPU,所以如果你的 CPU 过载,它可能会降低性能。尝试使用 rsync 和不使用 rsync -z,并在使用和不使用压缩的情况下配置您的 ssh。对所有 4 个组合进行计时,看看它们中的任何一个的表现是否明显优于其他组合。
  • 观察网络流量以查看是否有任何暂停。如果有停顿,您可以找到导致停顿的原因并在那里进行优化。如果 rsync 总是在发送,那么你真的是在你的极限。您的选择是:
    • 更快的网络
    • rsync 以外的东西
    • 将源和目标移得更近。如果你不能这样做,你可以 rsync 到本地机器然后 rsync 到真正的目的地吗?如果系统必须在初始 rsync 期间关闭,则这样做可能有好处。


小智 5

您也可以尝试 lsyncd,它只会在文件系统和更改的子目录上检测到更改时才进行 rsync。我一直在一个像样的服务器上使用它来处理多达 200 万个文件的目录。