跨云数据搬迁利器:Juicesync

本文作者 JuiceFS 工程师 Liyong,转载自 JuiceFS 官方博客

Juicesync 是什么

Juicesync 是 Juicedata 开源的多机分布式并行数据同步工具,支持各种对象存储( AWS S3, Azure Blob, Aliyun OSS 等)、 POSIX 文件系统、HDFS 间数据互相同步,包括文件或者对象的元信息(比如权限,Owner,修改时间)同步。Juicesync 使用 Go 语言开发,不到 一万行代码,核心同步逻辑只有几百行。

Juicesync 工作机制

Juicesync 将文件系统(POSIX 文件系统,HDFS 文件系统)中的文件视为对象存储中的对象,与已有的各种对象存储模型相统一。Juicesync 维护一个 FIFO 队列,list 任务不断列出源存储和目标存储的对象列表,比较源存储和目标存储的对象列表的差异及相同 key 对象元信息(数据大小,修改时间,Owner等)的差异,确定需要同步的对象 key 加入该 FIFO 队列,sync 任务不断从队列中获取需要同步的对象的 key 值,调用对象存储的 SDK 同步数据。 在多进程并行同步情况下,list 任务由 manager 进程执行,sync 任务由 worker 执行,manager 同时也是 worker 。

Juicesync 支持指定要同步的源对象的前缀和同步到目标存储的前缀,同时支持指定规则对同步的对象的 key 值进行过滤。

为什么需要 Juicesync

近年来,云计算越来越流行,企业从自身利益出发,或是不愿意被单一云服务商锁定,或是业务和数据冗余,或是出于成本优化考虑,会尝试将部分或者全部业务从线下机房迁移到云或者从一个云平台迁移到另一个云平台。

业务迁移涉及到数据的迁移。各个云平台产品类型类似,比如存储都有块存储、对象存储、归档存储等,尤其是对象存储,由于其高性价比、无限容量等特性,在数据备份、大数据、数据湖场景得到了广泛应用。

各云厂商的对象存储在 API 层面都会有或多或少的差异,每家云平台都有自己的客户端和 SDK。一般涉及服务和数据迁移,数据量都比较大,小则上百 TiB,多的能达到 PiB 级别,需要加大吞吐缩短迁移周期。市场上急需一个支持各类存储系统尤其是对象存储相互复制数据的工具,为了提高吞吐,需要能够做到多机并行。

目前已有的方案适用范围有限,比如 DistCp 依赖 Hadoop ,太重。Rclone 不支持多机并行。正好 JuiceFS 已经对接了各种对象存储的 API ,也实现了数据同步的逻辑,可以直接将这部分功能抽出来复用。

用户案例

流利说在跨云迁移中使用 Juicesync 同步 PiB 级别数据,没有出现任何数据异常,很好的支持了业务迁移。

开始使用

Juicesync 使用非常简单,只有一个二进制文件,可以直接从这里下载。

1. 并行的 rsync

# time ./juicesync data/ root@10.0.101.16:/tmp/data/2020/11/18 07:59:13.311063 <INFO>: Syncing from file:///root/tmp/data/ to root@10.0.101.16:/tmp/data/
2020/11/18 08:01:04.060726 <INFO>: Found: 10, copied: 10, deleted: 0, failed: 0/s

real	1m52.206s
user	0m35.433s
sys	0m23.877s

这里 data/ 目录下有 10 个大小为 1GiB 的文件,Juicesync 使用 SFTP 协议访问远端文件,使用 rsync 同步同样的数据,由于 rsync 是单线程,耗时是 juicesync 的 7.5 倍。

# time rsync -az data/ root@10.0.101.16:/tmp/data/real	13m50.555s
user	6m22.667s
sys	0m21.590s

2. 本地文件系统和对象存储间数据同步

将本地目录数据同步到 S3,在 AWS 上直接给服务器配置 IAM Role,Juicesync 支持自动根据对象存储 bucket 名称查找 bucket 的 endpoint :

# ./juicesync --threads=50 ./data2/ s3://jfs-test-tmp4/data2/
2020/11/18 09:24:28.741532 <INFO>: Syncing from file:///root/tmp/data2/ to s3://jfs-test-tmp4/data2/
[++++++                                       ]     1000  15%  4.2/s  210.9 MB/s

增加并发任务数到 50(默认为 10 )充分利用 CPU 和带宽。

3. 对象存储间的数据同步

在 2 核 4GiB 内存 EC2 节点从当前 region 的一个 bucket 拷贝到另一个 bucket,如下一行命令:

# ./juicesync --threads=50 s3://jfs-test-tmp3/data2/ s3://jfs-test-tmp4/data2/
2020/11/18 09:02:50.518509 <INFO>: Syncing from s3://jfs-test-tmp3/data2/ to s3://jfs-test-tmp4/data2/
[++++++++                                     ]     1000  18%  3.8/s  192.0 MB/s

使用多机并行同步,命令基本一样,仅加上一个 --worker 参数指定 worker 节点列表(发起节点为 manager 节点,manager 节点同时也作为一个 worker 节点):

# ./juicesync --worker=10.0.101.16 --threads=50 s3://**:**@jfs-test-tmp3/data2/ s3://**:**@jfs-test-tmp4/data2/
2020/11/18 09:00:15.458919 <INFO>: Listen at [::]:32887
2020/11/18 09:00:15.459295 <INFO>: Syncing from s3://jfs-test-tmp3/data2/ to s3://jfs-test-tmp4/data2/
2020/11/18 09:00:16.143205 <INFO>: launch a worker on 10.0.101.16/s  0.0MB/s
[+++++++++++++++++++++++++++++++              ]     1000  69%  8.4/s  421.9 MB/s

命令中 **:** 中的 ** 分别表示访问对象存储的 AKSK ,manager 节点通过 SSH 登录到 worker 节点启动 worker 进程。 双节点运行网络吞吐翻倍。

4. 其它一些有趣用法

  • 删除对象存储指定前缀下所有文件:

$ ./juicesync --delete-dst ./emptydir/ s3://jfs-test-tmp3/data/

在本地文件系统创建一个空目录,加上 --delete-dst 选项,会删除目标路径下存在但是源路径不存在的文件。

  • 忽略部分对象

$ ./juicesync --exclude='/2017-[0-9]{2}-[0-9]{2}/' s3://bucket1/prefix1/ oss://bucket2/prefix2/

--exclude 参数使用 POSIX ERE(egrep) 正则表达式。

上面命令将 S3 上 bucket1 桶的 prefix1/ 前缀下的对象同步到 OSS 上 bucket2 桶的 prefix2/前缀下,忽略 key 中包含有 /2017-[0-9]{2}-[0-9]{2}/ 的对象。比如 s3://bucket1/prefix1/2016-05-13/image.jpg 的对象同步到 oss://bucket2/prefix2/2016-05-13/image.jpg ,而 s3://bucket1/prefix1/2017-06-15/image.jpg 不会同步。