巨大的目录没有被更改的更快的rsync

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

不幸的是,networking到一些服务器是缓慢的。

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

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

由于networking速度很慢,我想避免发送每个文件80k次的信息。

有没有办法告诉rsync做一个子目录树的哈希总和?

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

更新

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

UPDATE2

一个目录树中有80k个文件。 每个单独的目录没有超过2k个文件或子目录

UPDATE3

有关networking缓慢的细节:

 time ssh einswp 'cd attachments/200 && ls -lLR' >/tmp/list real 0m2.645s 

tmp /列表文件的大小:2MByte

 time scp einswp:/tmp/list tmp/ real 0m2.821s 

结论:scp速度一样(没有意外)

 time scp einswp:tmp/100MB tmp/ real 1m24.049s 

速度:1.2MB /秒

一些无关的观点:

80K是很多文件。

一个目录中有80,000个文件? 没有任何操作系统或应用程序默认处理这种情况。 你只是注意到与rsync的这个问题。

检查你的rsync版本

现代的rsync处理大型目录比以前好很多。 确保你使用的是最新版本。

即使是旧的rsync也可以很好地处理大型目录,但是80k的文件并不大…这是很大的!

也就是说,rsync的内存使用量与树中的文件数成正比。 大型目录需要大量的RAM。 速度缓慢可能是由于任何一方缺乏内存。 在观看内存使用情况时进行testing。 Linux使用任何剩余的RAM作为磁盘caching,所以如果你在RAM上运行不足,磁盘caching就会减less。 如果用完RAM,系统开始使用交换,性能将会非常糟糕。

确保 – 不使用书签

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

把工作分成小批量。

有一些像Gigasync这样的项目,它将“通过使用perl来caching目录树,build立一小部分文件来与rsync进行传输”。

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

操作系统的默认设置不适用于这种情况。

如果你正在使用Linux / FreeBSD / etc等所有的默认设置,性能对所有你的应用程序来说都是很糟糕的。 默认情况下,假设小目录,以免浪费内存过大的caching。

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

看看“名字caching”

类似BSD的操作系统有一个caching,用于加快查找inode(“namei”caching)的名称,每个目录都有一个名字caching,如果它太小,则不仅仅是优化。由于rsync在每个文件上执行lstat(),所以80k文件中的每一个文件都可以访问inode,这可能会让你的caching变得模糊不清,研究如何调整系统中的文件目录性能。

考虑一个不同的文件系统

XFS被devise来处理更大的目录。 请参阅文件系统在一个目录中的大量文件

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

考虑计算正在读取多less个磁盘块,并计算您应该期望硬件能够读取多less块的速度。

也许你的期望太高了。 考虑有多less个磁盘块必须被读取来执行没有更改文件的rsync:每个服务器都需要读取目录并为每个文件读取一个inode。 假设没有任何内容被caching,因为80k文件很可能已经将你的缓​​存烧掉了。 假设保持math简单是80k块。 这大约有40M的数据,应该在几秒钟内读取。 但是,如果需要在每个块之间进行磁盘寻道,则可能需要更长的时间。

所以你将需要阅读大约80,000个磁盘块。 你的硬盘能做多快? 考虑到这是随机I / O,不是一个长线性读取,5分钟可能是非常好的。 这是1 /(80000/600),或每7.5ms读取一次磁盘。 对于您的硬盘驱动器来说是快还是慢? 这取决于模型。

基准反对类似的东西

另一种思考方式是这样的。 如果没有文件发生变化, ls -Llr会执行相同数量的磁盘活动,但不会读取任何文件数据(只是元数据)。 ls -Llr需要运行的时间是你的上限。

  • rsync(没有文件改变)比ls -Llr慢得多? 那么你正在使用的rsync选项可以改善。 也许-C被启用或者其他标志不仅仅是目录和元数据(inode数据)。

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

与你的开发者交谈

80k文件只是不好的devise。 很less文件系统和系统工具很好地处理这样的大目录。 如果文件名是abcdefg.txt,考虑将它们存储在abdc / abcdefg.txt中(注意重复)。 这将目录分解成更小的目录,但不需要对代码进行大的更改。

另外….考虑使用数据库。 如果在一个目录中有80k个文件,也许你的开发人员正在解决他们真正需要的是数据库的事实。 MariaDB或MySQL或PostgreSQL将是存储大量数据的更好select。

嘿,5分钟怎么了?

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

如果不需要提高性能,我假设你没有问这个问题。 但是,如果你的客户满意5分钟,宣布胜利,并转移到其他需要你的努力的项目。

更新:经过一番讨论,我们确定瓶颈是networking。 在我放弃之前,我会推荐两件事情:-)。

  • 尝试通过压缩来挤出更多带宽。 但是压缩需要更多的CPU,所以如果你的CPU超载,可能会使性能变差。 尝试使用和不使用-z rsync,并且使用和不使用压缩来configuration您的ssh。 时间所有4个组合,看看他们中的任何一个performance比其他人好得多。
  • 观看networkingstream量,看看是否有任何暂停。 如果有暂停,你可以find是什么造成他们,并在那里优化。 如果rsync总是发送,那么你真的是在你的极限。 您的select是:
    • 一个更快的networking
    • 除了rsync以外的东西
    • 将源和目标靠得更近。 如果你不能这样做,你可以rsync到本地机器然后rsync到真正的目的地? 如果在最初的rsync期间系统必须closures,那么这样做可能会有好处。

不,这在rsync中是不可能的,而在另外一个方面,效率会非常低下:

通常, rsync只比较文件修改date和文件大小。 你的方法会迫使它读取和校验所有文件的内容两次(在本地和远程系统上)以find改变的目录。

对于大量文件(很less发生变化)的同步,在源和目标分区上设置noatime也是值得的。 这为每个未更改的文件节省了对磁盘的写访问时间。