rsync用於數據遷移/備份的幾個細節


上周我們的一個GitLab服務頻繁出現web頁面卡死問題,得重啟虛擬機才可恢復,但重啟之后沒多久又會卡死。后來發現是虛擬機的磁盤大小超過了2T,而虛擬機管理那層的文件系統是ext3,最大單文件只能支持到2T(也不知道當初這個3T的虛擬磁盤鏡像是怎么建立起來的,難道Xen不會給出警告?)。由於該機房沒有可調動的磁盤了,於是只能另外找機房重新搭建一個環境,將數據遷過去。

只同步指定的子目錄

場景:
0) 要遷移的是gitlab里面的git庫數據

  1. 要遷移的數據很多(大約2T),由於跨機房網絡速度一般,我們期望先遷移部分重點用戶的,但fork出來的git庫是在不同的子目錄下的(比如 ssmp/ssmp.git會有zhangsan/ssmp.git, lisi/ssmp.git),這些都得一並遷移過去。

首先,像下面這樣直接將ssmp, zhangsan, lisi三個目錄全拷貝過去,肯定是不行的

rsync -a ssmp/ssmp.git zhangsan/ssmp.git lisi/ssmp git@new-repo:/home/git/repositories

因為不僅原來的目錄結構丟了,三個ssmp.git還混到一起了。

解決方法是用rsync的 filter 特性

rsync -a --delete  --filter="merge /tmp/gitlabFilter" repositories/ git@new-repo:/home/git/repositories/

但寫這個filter內容的寫法跟我們原來在tar那里習慣了的目錄排除不一樣,比如上面的場景寫成下面這樣是不能工作的:

+ ssmp/ssmp.git
+ zhangsan/ssmp.git
+ lisi/ssmp.git
- *

這是因為最后那個- *就已經把頂層的ssmp, zhangsan, lisi這幾個目錄排除掉了,於是ssmp下面的子目錄是沒法加進來的。

對於這個問題,rsync的man page說得很清楚(只不過我看見大段的英文就有些暈頭),需要寫成下面這樣:

+ ssmp/
- ssmp/*
+ ssmp/ssmp.git
+ zhangsan/
- zhangsan/*
+ zhangsan/ssmp.git
+ lisi/
- lisi/*
+ lisis/smp.git
- *

這里還有一個詳細的描述: Rsync backups: excluding directories

linux的磁盤cache導致拷貝速度逐漸下降

用rsync拷貝數據過程中發現一個現象:開始拷貝的時候速度很快,每秒有40MB左右,但拷貝幾十分鍾之后就降到10MB左右了,兩邊機器都沒有跑什么應用,網絡用netcat測也沒有問題…

然后我觀察到的一個問題是兩邊的free命令都顯示出內存占用很高,並且是buffered/cache一欄很高,因為這個緩存是可以手工釋放的,就抱着試試看的想法試了一下:

sync; echo 3 > /proc/sys/vm/drop_caches
ssh root@new-repos 'sh -c "sync; echo 3 > /proc/sys/vm/drop_caches"'

沒想到速度馬上恢復了!

於是我改了腳本,每次調用一次rsync同步完一個git庫及其fork,就調上面的語句將cache清掉,速度基本上不受影響。

補充說明

  1. linux操作系統會將文件系統的內容緩存起來,以便后面用到時加速,但在數據遷移場景下,基本上沒有“后面用到時”這個場景,這個緩存反而礙事(TODO: 為什么導致網絡io下降)
  2. 對於本機內大量拷貝文件,有人提供了一個nocache命令(https://github.com/Feh/nocache Debian/Ubuntu已經收錄了這個工具 https://packages.debian.org/search?keywords=nocache )。它的功能是臨時禁用cache,用法是將要執行的命令用nocache包住,比如: nocache cp -a ~/ /mnt/backup/home-$(hostname)
    ​,但rsync會使用網絡通訊,所以nocache rsync對遠端沒有作用( *Note however, that rsync uses sockets, so if you try a nocache rsync, only the local process will be intercepted.)
  3. 也有人在多年以前給rsync提交了一個補丁(https://bugzilla.samba.org/show_bug.cgi?id=9560 ),增加了--drop-cache選項,但遺憾的是沒被接納,說是過於linux-specific,開發人員的意見(見comment 3 )是改用nocache: nocache rsync -aiv --rsync-path='nocache rsync' some-host:/src/ /dest/. P.S. nocache工具的主頁最后在acknowledgements部分 說,其實它是衍生自rsync的這個補丁的。

參考資料:

已經備份過的文件不再重復拷貝(從舊備份硬鏈接未修改過的文件)

場景:要求每天建立一個備份。因為數據量很大,所以從備份速度、空間占用上來說,期望重復文件就不要重復拷貝了

第一個版本是這樣的:

rm -rf backup.2
mv backup.1 backup.2
cp -al backup.0 backup.1
rsync -a -l --delete source_dir backup.0

在上面的腳本中,多個備份之間的硬鏈接是依靠cp -a -l來建立的,而新增的文件依靠rsync -a -l也可以盡量硬鏈接已有的文件。

但這個腳本有點問題: 如果文件內容沒變,只是文件屬性(屬主、修改時間、權限)發生變化的話,rsync不會重新拷貝文件,而是直接修改原文件的屬性,而由於采用了硬鏈接,backup.1backup.2等舊備份目錄里面的文件屬性也發生了變化!

解決這個問題的方法是改為:

rm -rf backup.2
mv backup.1 backup.2
mv backup.0 backup.1
rsync -a --link-dest=backup.1 source_dir backup.0

注意這里的--link-dest=backup.1,它的含義是:先到backup.1這個目錄找找有沒有一樣的文件,有的話將其硬鏈接到目標目錄(backup.0),沒有的話再拷貝。屬性的變化會認為是不同的文件,會生成新拷貝。

如果文件屬性的變化對於你的場景沒有場景,那么兩種方法都可以用,第一種方法還能少一些拷貝文件。

參考資料

打包(archive)差異備份文件

場景:比較老的備份打包后轉到其它機器(或者磁帶機)上,每周一次全量備份,然后每天的增量單獨打包

rsync -a --compare-dest=backup.week backup.1 backup.incremental-20150604
cd backup.incremental-20150604
tar zcvf ../backup.incremental-20150604.tar.gz *

--compare-dest的含義跟上面--link-dest類似:先到這個參數指定的目錄找找有沒有想要的文件,如果沒有再從源目錄拷貝


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM