rsync 备份数据的底层原理

  • rsync+inotify=》制作异地镜像站点(实时同步)
    目的 : 为异地备份做好准备工作

rsync传递数据可以简单总结为三步

  1. 先验证用户身份
  2. 检查源路径到底需要传哪些文件,默认quick check算法
  3. 传输

rsync命令有上百个选项,主要分为两大类 :

  1. 一类是检测,检测是在源目录里面进行的。如果改变检测机制,一般情况下,会增加数据校验的可靠性,降低检查的效率。
  2. 还有一类是传输(比如要不要改变传输文件的属性),传输只传输源目录数据改动的部分。在源目录中,需要通过算法得出数据变化的部分,在目标目录中,也需要算法计算拼接出新的完整数据,覆盖到原文件。
    相比scp进行数据备份,rsync更加耗费cpu资源。

关于检测

  • quick check算法原理 : 只比较Modify(stat命令中修改文件内容的时间)和传输文件的大小,从远程拿到目标路径下所有文件的Modify和传输文件的大小,跟本地模块下的文件进行校验。
  • -c选项是改变了默认的quick check算法,采用hash算法来校验文件内容,从远程拿到目标路径下所有的文件,在源服务器中把拿到的文件的内容全部读一遍,进行数据的校验。
  • 大多数检查选项的调整,都会提升数据传输的可靠性,降低传输数据的效率。

关于传输

  • 传输只传输源目录数据改动的部分,目标目录收到源目录传输过来的数据后,会把本机的文件内容读出来,再把源目录传输过来的新的数据内容读出来,通过算法重新拼接成一份新的数据。
  • rsync总结
  1. 耗费cpu资源
  2. 源路径如果是频繁改动的,rsync不适合
  3. 不适合同步大文件

rsync选项补充

  • 本地命令
mkdir /test
mkdir -p /a/b/c/d/e
mkdir /dst
echo 123 > /a/b/c/d/e/1.txt

-R 选项:只取相对路径
rsync -a -R /a/b/c/d/e/ /dst			-R 拷贝/a以及目录下的所有子目录和文件
ls /dst
# a

rm -rf /dst/*
rsync -a -R /a/./b/c/d/e/ /dst			-R 拷贝当前目录下所有的子目录和文件
ls /dst
# b

rm -rf /dst/*
cd /a/b/c
rsync -a -R d/e /dst  			-R 拷贝当前目录下所有的子目录和文件	
ls /dst
# d

--backup 选项:保留更改前的文件内容(保留备份)
mkdir /a
mkdir /b
echo 111 > /a/1.txt
echo 222 > /a/2.txt
echo 333 > /a/3.txt
echo 666 > /b/1.txt
echo 777 > /b/2.txt

rsync -a --backup /a/ /b/				--backup 保留原文件的内容,默认在文件名后面加上~
ls /b
# 1.txt  1.txt~  2.txt  2.txt~  3.txt
ll /b
# total 20
# -rw-r--r-- 1 root root 4 Apr 18 17:01 1.txt
# -rw-r--r-- 1 root root 4 Apr 18 17:02 1.txt~
# -rw-r--r-- 1 root root 4 Apr 18 17:01 2.txt
# -rw-r--r-- 1 root root 4 Apr 18 17:02 2.txt~
# -rw-r--r-- 1 root root 4 Apr 18 17:01 3.txt
cat /b/1.txt~
# 666
cat /b/2.txt~
# 777

- 场景还原
rm -rf /b/*
echo 666 > /b/1.txt
echo 777 > /b/2.txt

--suffix 选项:修改保留文件名的后缀
rsync -a --backup --suffix=".bak" /a/ /b/		--suffix跟--backup连用,将默认的后缀~改成.bak
ls /b
# 1.txt  1.txt.bak  2.txt  2.txt.bak  3.txt
cat /b/1.txt.bak
# 666
cat /b/2.txt.bak
# 777

- 场景还原
rm -rf /b/*
echo 666 > /b/1.txt
echo 777 > /b/2.txt

--back-dir 选项:指定备份文件存放的目录位置(指定好备份文件存放的目录位置后,保留的文件将不会再加后缀)
rsync -a --backup --backup-dir=/b/bak /a/ /b/
ll /b
# total 12
# -rw-r--r-- 1 root root  4 Apr 18 17:01 1.txt
# -rw-r--r-- 1 root root  4 Apr 18 17:01 2.txt
# -rw-r--r-- 1 root root  4 Apr 18 17:01 3.txt
# drwxr-xr-x 2 root root 32 Apr 18 17:22 bak
ll /b/bak
# total 8
# -rw-r--r-- 1 root root 4 Apr 18 17:21 1.txt
# -rw-r--r-- 1 root root 4 Apr 18 17:21 2.txt
cat /b/bak/1.txt
# 666
cat /b/bak/2.txt
# 777

软连接与硬链接原理图

rsync 同步yum源_数据

  • 硬链接
echo 111 > a.txt
ln a.txt b.txt 						创建一个硬连接b.txt
echo 222 >> a.txt			
cat b.txt
# 111
# 222

ls -i a.txt							查看a.txt的inode号
# 33575024 a.txt
ls -i b.txt							查看b.txt的inode号
# 33575024 b.txt

rm -rf a.txt				
ls 
# b.txt
  • 软链接
echo 666 > 1.txt
ls -i 1.txt
# 33575032 1.txt
ln -s 1.txt 2.txt				创建一个软链接2.txt
ll 2.txt						软连接2.txt指向文件1.txt
# lrwxrwxrwx 1 root root 5 Apr 18 20:51 2.txt -> 1.txt
echo 777 >> 1.txt
cat 2.txt
# 666
# 777
ls -i 2.txt						1.txt与2.txt的inode号不一样
# 33754330 2.txt
rm -rf 1.txt					删除1.txt文件
cat 2.txt						无法查看2.txt的内容
# cat: 2.txt: No such file or directory

增量备份的底层原理

  • rsync的最大特点就是它可以完成增量备份,除了源目录与目标目录直接比较,rsync还支持使用--link-dest选项用来指定同步时的基准目录,即将源目录与基准目录之间变动的部分,同步到目标目录。
mkdir /data
echo 111 > /data/1.txt
echo 222 > /data/2.txt
ls -i /data/*						我们创建的data目录下的两个文件的inode号不一样,每一个文件的inode号都是不一样的
# 50365089 /data/1.txt  50365091 /data/2.txt
mkdir /bak/	
rsync -a --delete /data/ /bak/111/		备份data目录下的数据,将data目录下的数据备份到/bak/111/目录下
ls -i /bak/*						1.我们第一次同步数据,发现备份的数据跟data目录下的数据的inode号不一样(全量备份)
# 16816421 1.txt  16816423 2.txt
echo 333 > /data/3.txt						我们在data目录下添加新数据3.txt
ls /data									查看目录data下的文件内容
# 1.txt  2.txt  3.txt
rsync -a --delete --link-dest /bak/111/ /data/ /bak/222/			2.做增量备份,--link-dest指定了基准目录(/bak/111/),将源目录(/data/)与基准目录(/bak/111)之间变动的部分,拷贝到目标目录(/bak/222/)
ls -i /bak/111/*					
# 16816421 /bak/111/1.txt  16816423 /bak/111/2.txt
ls -i /bak/222/*					3.对比这两次数据的inode号,我们发现,数据相同的部分inode号是一样的
# 16816421 /bak/222/1.txt  16816423 /bak/222/2.txt  33575001 /bak/222/3.txt

- 我们下一次做增量备份的时候,目标目录/bak/222/就变成了基准目录,源目录还是/data/
rsync -a --delete --link-dest /bak/222/ /data/ /bak/333/
	.......
  • 结论 : rsync在做增量备份的时候,将上一次的数据和当前的数据进行对比。
  • 在指定的目录下,发生变化的数据部分会进行拷贝,没有发生变化的数据部分制作成硬链接。
  • 通过这种这种方法进行增量备份,弥补了数据恢复的效率问题,我们在做数据恢复的时候,直接找到相对应的时间点进行数据恢复就可以了。

增量备份脚本文件

vim /rsync.sh
	# !/bin/bash
	set -o errexit			# 脚本允许发生错误,终止运行
	set -o nounset			# 脚本碰到变量未定义终止运行(默认情况下,碰到变量不存在,会输出空继续运行)
	set -o pipefail			# 控制管道的输入输出(比如xxx|echo 123,出现这种情况会报错)
	
	readonly SOURCE_DIR="/data"					 # 备份的源目录
	readonly TARGET_START_DIR="/bak"			 # 目标目录的起始目录 
	readonly TARGET_DIR="${TARGET_START_DIR}/$(date '+%Y-%m-%d_%H:%M:%S')"		# 目标目录
	readonly LATEST_LINK="${TARGET_START_DIR}/latest"		 # 基准目录
	
	mkdir -p "${TARGET_START_DIR}"			 #	 先把目标目录的起始目录创建好
	
	rsync -av --delete \
	 "${SOURCE_DIR}/" \
	 --link-dest "${LATEST_LINK}" \
	# --exclude=".mp4" \	 	排除某些文件
	 "${TARGET_DIR}"
	# rsync -a --delete /data/ --link-dest /data/latest /bak/%Y-%m-%d_%H:%M:%S
	#                   源目录             	 基准目录     		 目标目录
	
	# 删除第一次的基准目录,然后将最新一次备份ok的目标目录链接到LATEST_LINK作为下一次的基准目录
	rm -rf "${LATEST_LINK}"
	# rm -rf /bak/latest
	ln -s "${TARGET_DIR}" "${LATEST_LINK}"
	# ln -s /bak/%Y-%m-%d_%H:%M:%S /bak/latest