问题场景

公司线上过期业务数据需要删除,删除前需要备份到本地一份。

思考

如何让传输速度够快?
分块多进程或多线程传输。

如何保证传输中断后,任务可以重新执行?
任务需要设置保活,传输失败能重新执行任务。

如何防止传输中断后,不至于全部重传,而是从中断处重新传送?
工具需要支持源目录和目标目录比较,传输增量部分。

远程文件同步到本地有哪些方式,优缺点?

1. scp

优点

  • 简单方便,安全可靠
  • 支持限速参数

缺点

  • 不支持排除目录
  • 不支持断点续传

用法

1
scp [参数] <源地址(用户名@IP地址或主机名)>:<文件路径> <目的地址(用户名 @IP 地址或主机名)>:<文件路径>

scp就是secure copy,是用来进行远程文件拷贝的。数据传输使用 ssh,并且和ssh 使用相同的认证方式,提供相同的安全保证。

2. rcp

优点

  • 传输速度快

缺点

  • 安全性差
  • 需要特殊配置

用法

目标主机需要事先打开rcp功能,并设置好rcp的权限:把源主机加入到可信任主机列表中,否则无法在源主机上使用rcp远程复制文件到目标主机。

3. wget

优点

  • 简单方便,支持排除目录
  • 支持限速参数

缺点

  • 只能从远程机器将文件或文件夹下载到本地
  • 远程机器需要支持ftp服务(例如启动proftpd)
  • 参数较多,使用上比scp复杂

用法

1
wget [参数] ftp://<目标机器ip或主机名>/<文件的绝对路径>  # proftpd格式

wget是一个从网络上自动下载文件的自由工具,支持通过HTTP、HTTPS、FTP三个最常见的TCP/IP协议下载,并可以使用HTTP代理。

4. rsync

优点

  • 功能强大,操作类似scp
  • 支持排除目录,支持限速参数
  • 支持断点续传和增量同步
  • 还支持本地复制

缺点

  • 暂无明显缺点

用法

1
rsync [参数] <源地址(用户名@IP地址或主机名)>:<文件路径> <目的地址(用户名 @IP 地址或主机名)>:<文件路径>

rsync是类unix系统下的数据镜像备份工具,从软件的命名上就可以看出来了——remote sync。它的操作方式和scp相似,但是比scp强大很多。使用双冒号分割主机名和文件路径时,是使用rsync服务器,这里不做介绍。

解决方案

基于以上分析,选择rsync作为主要工具来解决大文件夹同步问题:

1. 编写保活逻辑

使用rsync的内置重连机制,配合--partial--progress参数实现断点续传:

1
rsync -avz --partial --progress user@remote:/path/to/source/ /local/destination/

2. 编写多任务

使用--bwlimit参数限制带宽,避免影响其他业务:

1
rsync -avz --bwlimit=10000 --partial --progress user@remote:/path/to/source/ /local/destination/

使用--exclude参数排除不需要同步的目录:

1
rsync -avz --exclude='*.log' --exclude='tmp/' --partial --progress user@remote:/path/to/source/ /local/destination/

3. 补偿机制

使用--ignore-existing参数跳过已存在的文件:

1
rsync -avz --ignore-existing --partial --progress user@remote:/path/to/source/ /local/destination/

4. 完整的同步脚本示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/bin/bash

# 配置参数
REMOTE_HOST="user@remote_server"
REMOTE_PATH="/path/to/source/"
LOCAL_PATH="/local/destination/"
LOG_FILE="/var/log/sync.log"

# 创建日志目录
mkdir -p $(dirname $LOG_FILE)

# 执行同步
rsync -avz \
--partial \
--progress \
--bwlimit=10000 \
--exclude='*.log' \
--exclude='tmp/' \
--log-file=$LOG_FILE \
$REMOTE_HOST:$REMOTE_PATH \
$LOCAL_PATH

# 检查同步结果
if [ $? -eq 0 ]; then
echo "同步完成: $(date)" >> $LOG_FILE
else
echo "同步失败: $(date)" >> $LOG_FILE
fi

最佳实践总结

  1. 使用rsync进行大文件夹同步是最佳选择
  2. 合理使用--partial参数支持断点续传
  3. 使用--bwlimit参数控制带宽使用
  4. 使用--exclude参数排除不需要的文件
  5. 添加日志记录便于问题排查
  6. 脚本中加入错误处理机制确保同步可靠性