看了大佬提升SCP传输速度的文章
使用tar+lz4/pigz+ssh更快的数据传输:
http://www.orczhou.com/index.php/2013/11/tranfer-data-faster-on-the-fly/
加速scp传输速度:
http://www.orczhou.com/index.php/2013/11/make-scp-faster-with-cipher-and-compression/
[root@mysql141 binlog]# time scp -r mysql-bin.000214 172.25.2.142:/opt/soft/test_scp/ mysql-bin.000214 100% 1024MB 126.0MB/s 00:08 real 0m8.331s user 0m6.597s sys 0m2.721s [root@mysql141 binlog]# time scp -r -c aes192-cbc mysql-bin.000214 172.25.2.142:/opt/soft/test_scp/ mysql-bin.000214 100% 1024MB 177.4MB/s 00:05 real 0m5.959s user 0m4.444s sys 0m2.825s [root@mysql141 binlog]# time tar -c mysql-bin.000214|lz4 -B4|ssh -c aes192-cbc 172.25.2.142 "lz4 -d |tar -xC /opt/soft/test_scp" using blocks of size 64 KB real 0m4.024s user 0m5.049s sys 0m2.634s
闲来无事,想着scp为串行方式,可否使用并行方式再进一步提升速度,做了如下实验:
192.168.11.81读:
dd if=20210331.txt of=/dev/null bs=1M count=1000
1.8 GB/s
scp传输:
scp -c aes192-cbc 20210331.txt 192.168.11.82:~/
20210331.txt 100% 1000MB 114.2MB/s 00:08
192.168.11.82写:
dd if=/dev/zero of=20210331.txt bs=1M count=1000
892 MB/s
整体流程
磁盘读取--------->scp传输--------->落盘
>1.8 GB/s >114.2MB/s >892 MB/s
瓶颈还是在scp传输上,看看iperf测试带宽情况,114.2MB/s 明显没达到带宽极限
ethtool eth0|grep Speed
Speed: 1000Mb/s
iperf -c 192.168.11.82 -t 60 -f M
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-60.0 sec 28010 MBytes 467 MBytes/sec
iperf -c 192.168.11.82 -P 10 -t 60 -f M
[ ID] Interval Transfer Bandwidth
[SUM] 0.0-60.0 sec 29660 MBytes 494 MBytes/sec
现在想办法把scp传输这一过程速度发挥到极致,对比串行和并行的速度情况
造测试数据,10个1000M的文件:
for i in {1..10} do dd if=/dev/zero of=${i}_20210331.txt bs=1M count=1000 done
常规串行执行:
time scp -r -c aes192-cbc *_20210331.txt 192.168.11.82:~/ 10_20210331.txt 100% 1000MB 70.1MB/s 00:14 1_20210331.txt 100% 1000MB 75.7MB/s 00:13 2_20210331.txt 100% 1000MB 83.3MB/s 00:12 3_20210331.txt 100% 1000MB 76.6MB/s 00:13 4_20210331.txt 100% 1000MB 78.1MB/s 00:12 5_20210331.txt 100% 1000MB 76.6MB/s 00:13 6_20210331.txt 100% 1000MB 76.8MB/s 00:13 7_20210331.txt 100% 1000MB 83.2MB/s 00:12 8_20210331.txt 100% 1000MB 77.3MB/s 00:12 9_20210331.txt 100% 1000MB 83.3MB/s 00:12
real 2m11.144s
user 1m2.778s
sys 1m20.256s
编写并行执行脚本parallel_scp.sh,内容和执行方式如下:
#脚本传值依次是:文件名(支持通配符) 目标IP 目标路径 scp并发数
sh parallel_scp.sh '*_20210331.txt' 192.168.11.82 '/root/' 10
cat parallel_scp.sh #!/bin/bash fileName=$1 remoteHost=$2 remoteDir=$3 maxScp=$4 ls ${fileName} > filelist.lst cat filelist.lst | while read line do scpNum=`ps -ef| awk '{print $8}' |grep ^scp|egrep -v 'grep|tail'|wc -l` while [ ${scpNum} -ge ${maxScp} ] do sleep 5 scpNum=`ps -ef| awk '{print $8}' |grep ^scp|egrep -v 'grep|tail'|wc -l` done scpFileName=`echo ${line}| awk '{print "scp_"$0".sh"}'` echo "scp -r -c aes192-cbc ${line} ${remoteHost}:${remoteDir}" > ${scpFileName} time nohup sh ${scpFileName} > ${scpFileName}.out 2>&1 & #echo "当前进度:nohup sh ${scpFileName} > ${scpFileName}.out &" done #echo "传输完成。"
sh parallel_scp.sh '*_20210331.txt' 192.168.11.82 '/root/' 10
real 1m12.449s
user 0m5.911s
sys 0m5.150s
通过理论和测试实验的执行时间来看,并行的scp会比串行时间快。
以上都是基于文件大小相同,若需要传输的文件大小不一,要是并行执行时,同一批并行的都是大文件,或者都是小文件,传输速度肯定是不均衡的,下面考虑把同一批并行的文件组合成大小差不多
ls -lS /root/*_20210331.txt|awk '{print $9}' > 123456.txt--按文件大小排序,由大到小倒序排
123456.txt 存在100行,内容为
/root/1_20210331.txt --10G
/root/2_20210331.txt --9G
....
/root/100_20210331.txt --1MB
awk '{lines[NR]=$0} END{i=50; while(i>0){print lines[i];--i}}' 123456.txt >p1.txt --倒序排列文件,100个文件中前50大小的文件倒序排
awk '{lines[NR]=$0} END{j=51; while(j<101){print lines[j];++j}}' 123456.txt >p2.txt --顺序排列文件,100个文件中前50大小的文件顺序排
方法一:
paste -d "\n" p1.txt p2.txt >c.txt --逐行交叉合并两文件,c.txt的内容为均分大小后的文件排序
方法二(unix环境不一定存在paste命令):
将两个文件的内容按行交叉合并
for ((i=1;i<=$line;i++));do
cat a.txt | tail -n +$i |head -n 1 >>c.txt #提取p1.txt的第i行,追加到c.txt
cat b.txt | tail -n +$i |head -n 1 >>c.txt #提取p2.txt的第i行,追加到c.txt
done
这里最后的c.txt,替换到脚本里面的filelist.lst,就可以调用parallel_scp.sh执行了。
总结:
1、这里采用并行把scp速度发挥到极致,并未考虑性能影响,生产环境需要谨慎使用。
2、对于很大的二进制文件(data类型),考虑使用tar+lz4/pigz+ssh数据传输。
3、类比,对于相同串行执行的ftp、sftp等传输工具,也可考虑使用该方式,脚本稍微改一下就行。