@雨翌 说想知道镜像源是如何工作的,我们就来说一说这个。其实要做一个镜像源,需要搞定的有两件事:一是如何向广大用户提供下载服务,一条httpd start就搞定了;二是如何与上游同步,然而这种东西也一条rsync就搞定了
关于rsync
rsync提供了一种快速的文件同步的机制。一般的diff算法需要分别遍历两个文件,然而这种功能并不适用于远程传输:如果我能够同时获得需要同步的两个文件,再diff他们就没什么意义了。rsync使用的算法并不是特别复杂,可以Google The rsync algorithm 搜到Andrew Tridgell在1996年的论文,man rsync可以得到使用说明。
镜像源中使用rsync
rsync是目前各种镜像源同步的标配,基本没有第二种选项。对于镜像源来说,在同步过程中还需要考虑另一个问题:一般的仓库都是带有索引的,就是用apt-get update更新的那些东西。这些索引指明了服务器上具有哪些文件,以备包管理器查询。如果我们在同步的时候更新了索引,却没有更新完新的包;或是删掉了原来的包,却还没有更新索引,此时如果包管理器进行操作的话,将会出现问题。
rsync具备两个特别有用的选项:一个是delete-after,一个是–delay-updates。第一个选项能够令rsync在完成所有其他传输之后,再删除本地中那些上游没有的文件;第二个选项能够使rsync将所有需要更新的文件全部暂存至一个缓存目录,待所有传输完成后在本地一次性地对所有暂存的新文件进行move。这使得在传输过程中不会修改本地文件,减少了文件状态“不一致”的时间。一些仓库使用了这两个选项来完成同步,比如Archlinux。
然而对于大仓库来说,批量move的时间还是太长。如果想要进一步降低这个影响,可以使用“两阶段同步”。第一个阶段只同步包文件,不同步索引、也不删除本地的旧包;第二个阶段再进行索引的更新和删除包的操作。这样的话进一步降低了同步对用户的影响。Debian使用这种方式进行同步。
这一定能保证“同步”吗?
不一定。如果我们在同步的过程中,上游的文件发生了变化(这很有可能发生,因为上游往往还需要与上上游同步),将会导致我们同步结束之后文件的状态仍然不一致。而且很遗憾,目前仅凭rsync一人之力,无法解决这个问题。
Debian官方提供了一个脚本,在同步过程中如果上游的文件发生变化,下游服务器将会收到通知,此时应当重新同步。如果整个同步链都使用了这个脚本,将会很大程度上保证文件状态的一致。
除此之外,加粗水管、提高同步频率,都有助于缓解这个问题。
定时同步
一般来说crontab就可以搞定了,这是另一个男人,请man crontab。