高效备份策略:利用 Rsync与压缩技术优化数据同步

0. 太长不看

【由 ChatGPT 4.0 进行总结, thanks to 章魚燒吃章魚】
这篇文章介绍了使用Rsync进行增量传输的备份策略,特别是在处理TiDB集群和WSL系统备份的场景。
作者分析了备份流程的各个阶段:导出、压缩、传输和校验,着重讨论了压缩和传输阶段的优化方法。

  • 对于压缩,推荐使用pigz以及考虑了Facebook的zstd;
  • 在传输方面,通过调整Rsync和SSH的参数配置,显著提高了传输效率。

文章还探讨了如何利用Rsync的增量传输能力,通过保持远端最新文件的副本,实现更高效的数据同步。
整篇文章提供了一套详细的优化策略,旨在提高备份过程的效率和性能

1. 背景

目前接手了公司部分 TiDB 集群的备份任务的维护,再加上自己也需要对自用的 WSL 系统进行日常备份,记录一下一些调研的过程。

2. 流程

整体来讲,一个备份流程可以分为三部分: 导出 -> 压缩 -> 传输 -> 校验。
当前使用的工具分别为: dumpling -> pigz -> rsync -> md5sum。
pigz 和 rsync 相信都不陌生, dumpling 是 TiDB 官方出品的一个类似于 Mydumper 的工具,对于 TiDB 的场景做了更多的兼容。
本身 dumpling 的参数配置已经调优过了,并没有什么能做的地方,以下主要针对 压缩 和 传输 两个场景说明。

PS: 在调研过程中,额外发现了 MyDumper 在 22 年下半年实现了流式导出的功能,在备份机器空间不足的情况下很有优势,同时流水线的实现也能提高整体的效率。
难点在于,相较于 mysqldump 的实现, MyDumper 是多线程的,这种情况下下很难做到 pipe。
为此他们专门写了一篇文章: MyDumper’s Stream Implementation, 感兴趣可以去瞄瞄。

3. 压缩

使用 pigz 是一个不错的选择,参考美团的文章: 速度与压缩比如何兼得?压缩算法在构建部署中的优化,

Pigz 是 gzip 的并行实现的缩写,它主要思想就是利用多个处理器和核。它将输入分成 128 KB 的块,每个块都被并行压缩。每个块的单个校验值也是并行计算的。它的实现直接使用了 zlib 和 pthread 库,比较易读,而且重要的是兼容 gzip 的格式。Pigz 使用一个线程(主线程)进行解压缩,但可以创建另外三个线程进行读、写和检查计算,所以在某些情况下可以加速解压缩。

这样子, 既能充分利用现代处理器的多核也能保证整体的兼容性。
另一个备选是 Facebook 搞出来的 zstd, 验证了一下,能在稍微增大压缩文件的体积下(3~5%)减少约 50% 备份的时间。缺点就是需要安装额外的软件并更改当前的备份链路。考虑到改动过大,同时目前瓶颈不再压缩阶段,做为优化项暂时搁置了。

4. 传输

4.1 参数惹得祸

这块是整体优化的核心点。原因在于接手之后观察耗时,传输时间占了大头, 算了一下速度居然在 20~30 M/s。这简直是难以想象。
想知道原因不妨先来看看之前的传输命令:

rsync -avz --progress -e 'ssh -p 22' --bwlimit=200000 /tmp/temp.tar.gz [email protected]:/tmp/

一眼看过去,挺正常啊, 但是先注意到参数(结合 rsync 的 man 文档)

  • -z 参数是开启压缩的意思, compress file data during the transfer
    同时, 我们传输的文件提前经过了 pigz 做压缩,这时候再开启 -z 参数,就相当于压了又压,白费功夫
    同时, rsync 的压缩是单线程的(这个文档中没提到,但是手动跑一次观察一下负载就能证明), 也就意味着之前是 pigz 优化也是白费功夫。
    去掉 -z 参数, 哗的一下就来到了 170 M/s, 感天动地。

4.2 ssh 再优化

我们都知道,rsync 在实际的连接中可以用 ssh 或 rsh, 前者占大头, 同时也是默认的配置。在这种情况下,优化 ssh 传输也就相当于优化 rsync 传输。
一般情况下, ssh 由三个比较重要的步骤组成:

  1. key exchange algorithm => 用于秘钥交换的算法(类似于 TLS 中非对称加密交换对称加密的秘钥)。
  2. ciphers => 使用的对称加密算法。
  3. MACs => Message authentication code , 类似于做校验。

在内网数据备份传输的场景下,我们可以几乎忽略安全性(内网都不安全了,那要ssh安全性有啥用)。同时,数据正确性有 rsync 和紧随其后的 md5sum 进行多重保障。
因此,根据部分 benchmark: 加速scp传输速度, Benchmarking SSH connection: What is the fastest cipher algorithm for RPi? 和我们的测试验证,使用了 blowfish 加密算法。
灰度下来,小幅提升了传输效率(达到了 limit 的 200M/s) 并降低了双边的 cpu 消耗。

5. 增量传输

我们都知道, rsync 是可以做增量传输的。那为啥在压缩文件情况下没人用嘞? 原因在于:

Normally, when you compress a file, even a 1 byte change can cause the entire compressed file afterwards to be completely different. This isn’t great for rsync, since it will only upload the delta, but the delta will be the whole file even for a 1 byte change.

考虑到用 rsync 做备份是个常见的需求,zstd 和 gzip 都针对该场景提供了一个参数叫: rsyncable。开始该参数会定期重置 synchronization point, 尽可能地保证差异的内容不会传导到整个文件,即 1 byte 的变化可能会导致 1%的差异但不会导致 100% 的差异。可控的 diff 带来了 rsync 增量传输友好的特性。
相关的讨论和细节的解释可见: zstd: zstd rsyncable option, gzip: Rsyncable gzip

6. 整合

基于此,我们得以重新设计整体的传输流程:

  1. 在远端保留一个最新的文件
  2. pigz / pzstd 开启增量备份模式
  3. 每次备份时,先 ssh 到远端去 cp 一份最新的文件到归档文件夹中,再用 rsync 去增量同步到当前最新的文件

这种情况下,若是新旧备份文件的变化不大,能近乎实现增量传输的功能。

7. 有用的其他链接

  1. 使用tar+lz4/pigz+ssh更快的数据传输
  2. RSYNC 的核心算法