Rsync(remote synchronize)是一个远程数据同步工具,它可以将一个目录的文件快速地同步到另一个目录,还可以通过网络快速同步多台主机间的文件。rsync 使用所谓的“rsync算法”来使本地和远程两个主机之间的文件达到同步,这个算法只传送两个文件的不同部分,而不是每次都整份传送,因此速度相当快。

Rsync 工作模式

一般而言,rsync 是 C/S 模型的一个软件,它既是客户端程序也是服务端程序。也就是说 rsync 需要启动一个守护进程(daemon)来接收客户端的请求,默认监听在 TCP 873 端口。

rsync 也支持独立使用以及配合 SSH 通道来传输数据,下面会有几种用法的详细说明。

Rsync 适用场景

  • rsync 在同步文件时需要非常频繁的计算文件的校验码,因此 rsync 会占用一定的 CPU 资源。

    如果不希望 Rsync 进行增量文件传输,则使用 --whole-file 参数显式指定为全量传输。

  • rsync 不适合对数据库文件进行实时同步

    像数据库文件这样的大文件,且是频繁访问的文件,如果使用rsync实时同步,发送端要计算、比较的数据块校验码非常多,cpu会长期居高不下,从而影响数据库提供服务的性能。另一方面,接收端每次都要从巨大的basis file(一般提供服务的数据库文件至少都几十G)中复制大部分相同的数据块重组新文件,这几乎相当于直接 cp了一个文件,它一定无法扛住巨大的io压力,再好的机器也扛不住。

    所以,对频繁改变的单个大文件只适合用rsync偶尔同步一次,也就是备份的功能,它不适合实时同步。像数据库文件,要实时同步应该使用数据库自带的replication功能。

  • 可以使用 rsync 对大量小文件进行实时同步
  • 由于rsync 是增量同步,所以对于接收端已经存在的和发送端相同的文件,发送端是不会发送的,这样就使得发送端和接收端都只需要处理少量的文件,由于文件小,所以无论是发送端的 CPU 还是接收端的 IO 都不是问题。

    但是,rsync 的实时同步功能是借助工具来实现的,如 inotify+rsync,sersync,所以这些工具要设置合理,否则实时同步一样效率低下,不过这不是 rsync 导致的效率低,而是这些工具配置的问题。

Rsync 增量同步原理

先看一个场景,客户端A和B,以及服务端都保存了同一个文件,最初,A、B和服务端上的文件内容都是相同的(记为 Version 1)。某一时刻,B修改了文件内容(记为 Version 2),上传到服务端上。客户端A这时试图向服务端更新文件到 Version 2。

上面这个场景很常见,例如现在流行的网盘。假设我有一个文件a.txt在网盘上,上班时在公司的单位PC上更新了文件a.txt,下班后回到家里,家里PC硬盘上的a.txt就不是最新的内容,这时网盘就试图从服务器上去拿最新的a.txt了。

那么问题来了,如果在公司电脑上我只是更新了a.txt里很少的一部分内容,例如a.txt共有20M,我只更新了10个字节,难道家里的电脑上,网盘要从服务器上下载20M大小的文件?这明显很浪费带宽。

rsync算法就是用来解决上述问题的。在上述的场景中,A需要向服务器同步文件发送它所保存的文件(Version 1)少量的rsync摘要,服务端拿到后对比本地的文件(Version 2)内容,得到Version 1 对比 Version 2 的变化,然后通过仅将变化部分发送给A,A收到之后再把数据和原来的文件进行合并,因此就得到了完整的 Version 2 文件了,这样大大减少了网络传输数据。下面详述rsync算法的步骤。

  • 首先,rsync 需要客户端与服务端之间约定一个块大小,比如 1K。然后把需要同步的文件等分成多个 1K 大小的块,每块各计算出 MD5 摘要和 Alder32 校验和,然后将校验信息发给服务端。

    分块校验示意图.png

  • 服务端收到摘要信息和校验和后,把本地的文件(Version 2)也按协商好的 1K 的大小从文件的0字节开始切出一块,计算出 Alder32 校验和,然后与客户端发过来的第一块数据的 Alder32 进行比较。

    • 如果两个块的 Alder32 值不同,则表示文件内容是不相同的。接着,把文件(Version 2)从1字节开始切出一块,再对比 Alder32 的值。如此循环。
    • 如果两个块的 Alder32 值相同,则进一步比对 MD5 值,两者都相同,则认为数据是相同的,则继续比对下一块,如此循环。

    比较绕,通过一张示意图来补充说明一下流程。

rsync分块比较示意图.png

  • 服务端比较出差异部分数据,把差异部分数据发给客户端
  • 客户端收到差异部分数据,在本地合并数据,得到 Version 2

Rsync 的几种常用同步模式

本地模式

本地模式即在同一个系统中,将一个目录/文件同步到另一个目录/文件的方式,此使用方式可以理解为 cp 命令的增强版本。

常用的使用方式如下:

# 将 src 目录里的所有文件同步至 dst 目录(不包含 src 本身)
rsync -av src/ dst/

# 将 src 目录同步至 dst 目录
rsync -av src dst/

# 同上,使用 -R 参数,即使是 src 后面有 /,也会同步目录本身
rsync -avR src/ dst/

daemon 模式

daemon 模式即在两台主机将同步文件,其中一台需要开启一个 rsync daemon 进程。另一台作为客户端使用,客户端可以将本地文件/目录推到服务端,可以从服务端拉取文件/目录到本地。

用一张图来说明两者的区别:

rsync.push.pull.png

命令:

# rsync server
rsync --daemon -config=/etc/rsyncd.conf

# rsync client
rsync -avz /data [email protected]::backup

SSH 模式

SSH 模式即 rsync 通过 SSH 隧道来传输数据,其各有优缺点

优点:

  • 加密传输
  • 无需 rsync daemon

缺点:

  • 通过 SSH 承载,效率低
  • 需要输入密码或配置免密码登录,或使用其它能自动输入密码的工具

常用命令:

# 将 src 目录同步到 192.168.1.1 的 /backup 目录
rsync -avR src [email protected]:/backup/

# 如果 SSH 端口不为 22,使用 -e 参数指定 SSH 端口
rsync -avR src -e 'ssh -p2222' [email protected]:/backup/

# tips:使用 SSH 隧道模式,需要输入 SSH 密码,如果不想输入密码,需要配置 SSH 免密码登录

标签: rsync

添加新评论