三款面向 Amazon S3 的开源文件同步工具之对比

2010-03-28

受 @Sisyphusliu 师兄的启发,我最近决定试用 Amazon S3 来做个人数据同步与备份。初步计算发现这很可能比之前使用 VPS 或 Web 主机的方案要节约成本。我对三款面向 Amazon S3 的开源文件同步工具进行了对比,将其中部分细节说明如下,供有相同需求的朋友参考。

这三款工具分别是 jets3t、s3cmd 和 s3sync.rb。其主要特性和附加功能这里不再赘述,它们的官方主页都有详细说明。软件的稳定性还有待长时间使用的考验,但从网上没有发现用户反映太大的问题。我在这里强调它们存储文件元信息的差别,以及由此可能引发的问题。

jets3t s3cmd s3sync.rb
打包大小 12MB 50KB 30KB
开发语言 Java Python Ruby
官方主页 http://bitbucket.org/jmurty/jets3t/ http://s3tools.org/ http://s3sync.net/
最后更新 2010-3 2009-10 2008-6
功能定位 综合工具集+文件管理GUI 命令行工具集 命令行工具集
文件元信息 Content-Type
jets3t-original-file-date-iso8601
md5-hash
Content-Type
s3cmd-attrs
Content-Type
group
owner
permissions
目录元信息 Content-Type
jets3t-original-file-date-iso8601
Content-Type
group
owner
permissions

由于 S3 基于 Key-Object 存储方式,与树型文件系统不同,因此如何将树型结构组织的文件及其元信息存储在 S3 中就是一个问题。这三款工具都将文件的全路径作为 Key,并把文件的元信息保存在 Object 的自定义属性中。

这样有什么后果呢?首先看目录。稍稍想想就会发现,像“a/b/c”这样的 Key 无法直接判定“c”是一个目录还是一个文件。s3cmd 的处理最简单,它的任何一个 Object 都是文件,不把目录作为 Object 保存。这样消除了歧义,但导致了目录的元信息无从保留,同时也无法保存空目录。而 jets3t 和 s3sync.rb 会保存目录的 Object,并通过元信息中的 Content-Type 来区别文件与目录。这样就保留了目录元信息,也允许空目录存在,但这影响了工具之间的互操作性。下载另一个工具上传的文件时,工具彼此不认识对方的目录 Object,就会将它们保存成普通文件,从而造成同名的目录无法创建。

再来看看文件的元信息。s3cmd 保存的 s3cmd-attrs 属性是一个包含了 uid、gid、uname、gname、mtime、atime、ctime 等信息的字符串,因此它保留了最完整的文件元信息。jets3t 只保存文件修改时间,无从得知属主与权限,不适合保存可执行程序的目录;s3sync.rb 只保存属主与权限,而且是数字 id 而非名字,在新系统中恢复数据时可能出现映射错误。

我个人倾向于选择 s3cmd。其一,文件修改时间和权限对于个人程序、文档来说是比较重要的信息。当然这不是技术问题,修改 jets3t 和 s3sync.rb 肯定也能做到。其二,不使用自定义的目录 Object 就允许一定程度的互操作,例如使用 jets3t 和 s3sync.rb 可以直接下载 s3cmd 上传的文件与目录结构(元信息丢失)。而 s3cmd 设计造成的目录元信息缺失、空目录消失等问题,对一般应用和文档来说不太重要、相对容易恢复。当然也可以使用额外的机制来记录目录元信息,但考虑 KISS 原则,s3cmd 目前的设计还是有道理的。要想同时解决元信息与目录问题,容易想到的办法是将目录打包或压缩再上传,这比较适于长周期的文件归档备份场景,但对于细粒度、短周期的日常数据同步场景并不适合。

至于云存储的信任问题,在现阶段我也只能选择折衷。一方面不要将鸡蛋放在一个篮子里,重要数据还是需要异地备份的。另一方面可以使用这些同步工具自带的安全机制,或自己稍加封装实现数据加密。

最后提醒大家,务必看看 Joel 的备份观