在S3存储桶之间移动文件的最佳方法?


89

我想每天将一些文件从生产存储桶复制到开发存储桶。

例如:将productionbucket / feed / feedname / date复制到developmentbucket / feed / feedname / date

由于我想要的文件在文件夹结构中非常深,因此转到每个文件夹并进行复制/粘贴非常浪费时间。

我一直在尝试将驱动器安装到每个存储桶并编写Windows批处理脚本,但这非常慢,并且不必要地将所有文件/文件夹下载到本地服务器并再次备份。

Answers:


109

更新资料

正如alberge(+1)所指出的那样,如今,出色的AWS Command Line Interface提供了与(几乎)所有AWS交互的最通用方法-同时涵盖了大多数服务的API,并且还具有更高级别的S3命令来处理您的AWS。具体来说,请参阅适用于S3AWS CLI参考

  • 同步 - 可同步目录和S3前缀。示例2涵盖了您的用(还提供了的更精细的用法--exclude--include以及前缀处理等):

    以下同步命令通过复制s3对象,将指定前缀和存储桶下的对象同步到另一个指定前缀和存储桶下的对象。[...]

    aws s3 sync s3://from_my_bucket s3://to_my_other_bucket
    

为了完整起见,我将提到较低级别的S3命令仍然可以通过s3api子命令使用,这将允许在最终采用其更高级别的功能之前,将任何基于SDK的解决方案直接转换为AWS CLI。


初步答案

在S3存储桶之间移动文件可以通过PUT对象-复制API(随后是DELETE Object)来实现:

PUT操作的此实现会创建已存储在Amazon S3中的对象的副本。PUT复制操作与先执行GET然后执行PUT相同。添加请求标头x-amz-copy-source可使PUT操作将源对象复制到目标存储桶中。资源

所有现有的AWS开发工具包都有相应的示例,请参阅“ 在单个操作中复制对象”。自然地,基于脚本的解决方案显然是这里的首选,因此,使用适用于Ruby的AWS开发工具包复制对象可能是一个不错的起点。如果您更喜欢Python,当然也可以通过boto来实现,请参见方法copy_key() boto的S3 API文档中的方法

PUT Object仅复制文件,因此DELETE Object在成功执行复制操作后,您仍需要通过静止方式显式删除文件,但是一旦处理了存储段和文件名的整个脚本到位(仅存在几例) ,请参见例如,每个请求删除一个对象)。


我最终使用.NET中的AWS开发工具包编写了操作脚本
Matt Dell

1
@MattDell您可以为该问题添加.NET答案吗?
balexandre

1
令人不解的是,Amazon不清楚复制命令是否成功,因此操作后的删除似乎很危险。
James McMahon

为了清楚起见,我专门指的是Java API。我打开了一个单独的问题stackoverflow.com/questions/17581582
James McMahon

我们仍然需要一些简单的方法来制作能够从一个存储桶读取并写入另一个存储桶的单个ID和密钥。尤其是如果这些存储桶跨多个帐户。
CMCDragonkai

65

新的官方AWS CLI本机支持的大多数功能s3cmd。我以前一直在使用s3cmdruby AWS开发工具包或ruby AWS开发工具包来做类似的事情,但是官方CLI对此非常有用。

http://docs.aws.amazon.com/cli/latest/reference/s3/sync.html

aws s3 sync s3://oldbucket s3://newbucket

4
这应该被投票到列表的顶部。这是同步存储桶和所有这些答案中最新的正确方法。
2014年

如果您遇到403访问被拒绝的错误,请参阅此博客文章。它有帮助。alfielapeter.com/posts/...
crlane

3
跨区域副本aws s3 sync s3://my-bucket-in-eu-west1 s3://my-bucket-in-eu-central1 --source-region=eu-west-1 --region=eu-central-1
等效

如果您需要在服务器上使用运行此奥尔晚上nohup aws s3 sync s3://my-bucket-in-eu-west1 s3://my-bucket-in-eu-central1 --source-region=eu-west-1 --region=eu-central-1 & thegeekstuff.com/2010/12/5-ways-to-execute-linux-command
equivalent8

@alberge是否可以使用命令行参数提供访问密钥和秘密?
–EmptyData

28

要从一个存储桶移动/复制到另一个存储桶或同一存储桶,我使用s3cmd工具,并且工作正常。例如:

s3cmd cp --recursive s3://bucket1/directory1 s3://bucket2/directory1
s3cmd mv --recursive s3://bucket1/directory1 s3://bucket2/directory1

28

我花了几天的时间编写自己的自定义工具来并行化为此所需的副本,但是随后我浏览了有关如何获取AWS S3 CLI sync命令以使存储桶与大规模并行化同步的文档。以下命令将告诉AWS CLI使用1,000个线程来执行作业(每个文件或一个多部分副本的一部分)并预执行100,000个作业:

aws configure set default.s3.max_concurrent_requests 1000
aws configure set default.s3.max_queue_size 100000

运行这些命令后,可以使用简单的sync命令,如下所示:

aws s3 sync s3://source-bucket/source-path s3://destination-bucket/destination-path

在m4.xlarge机器上(在AWS--4内核中,具有16GB RAM),对于我的情况(3-50GB文件),同步/复制速度从大约9.5MiB / s变为700 + MiB / s,速度提高了是默认配置的70倍。

更新:请注意,S3CMD已经更新了多年,这些更改现在仅在您处理大量小文件时才有效。另请注意,Windows(仅在Windows上)的S3CMD总体吞吐量受到严重限制,无论您使用何种实例大小或设置,每个进程只能达到约3Gbps。像S5CMD这样的其他系统也有同样的问题。我已经与S3团队进行了交谈,他们正在对此进行调查。


谢谢,通过您的配置成功获得超过900 + MiB / s的速度,超过了默认速度。
kozyr

@James:API是否会限制我们实现如此高速的传输?我正在使用由T2 EC2计算机上的AWS Java SDK vs CLI提供的transfermanager api来传输2 GB文件。时间差约为(CLI-14秒)与(SDK-80秒)的5.5倍。另外,我在SDK中看不到s3.max_queue_size的任何选项。任何意见?
Dwarrior

@Dwarrior,这两个设置都用于CLI。使用SDK时,您必须自己管理所有请求排队。AWS支持声称使用Linux达到了EC2和S3之间最大可能吞吐量的大约80%(即,公布的EC2实例网络吞吐量)。Windows是AWS上的第二等公民,使用Amazon提供的工具无法获得Windows的一半,而且看来他们不打算对其进行修复。:-(随着T2机,AWS不指定正是你多少带宽得到的,虽然事情有些改进,如果你设置了一个S3 VPC端点。
詹姆斯

@James一直到将我的文件列表通过Spark并行化到集群的程度,再结合每个分区中的并行化,然后使用transfermanager进行任何给定文件的并行上传。在此之后,我看到从80秒改善到45秒,但是仍然缺少CLI从EC2处理的方式。谢谢,尽管如此。它也大大提高了Windows的性能。在SDK中,我们可以设置最大连接数,但不能设置队列大小,因此我认为我们可能不得不放弃它。:)有关如何管理队列的任何指针,我可以作为基准的任何示例代码。
Dwarrior19年

2
S5Cmd(github.com/peakgames/s5cmd)是AWS支持人员用来实现最大吞吐量的实用程序。实例大小确实有很大的不同。新的c5n系列对于网络来说非常具有成本效益,并且一直达到惊人的100Gbps。
詹姆斯

13

要求的.NET示例:

using (client)
{
    var existingObject = client.ListObjects(requestForExisingFile).S3Objects; 
    if (existingObject.Count == 1)
    {
        var requestCopyObject = new CopyObjectRequest()
        {
            SourceBucket = BucketNameProd,
            SourceKey = objectToMerge.Key,
            DestinationBucket = BucketNameDev,
            DestinationKey = newKey
        };
        client.CopyObject(requestCopyObject);
    }
}

客户就像

var config = new AmazonS3Config { CommunicationProtocol = Protocol.HTTP, ServiceURL = "s3-eu-west-1.amazonaws.com" };
var client = AWSClientFactory.CreateAmazonS3Client(AWSAccessKey, AWSSecretAccessKey, config);

也许有更好的方法,但这只是我编写的一些用于传输某些文件的快速代码。


1
这似乎是一个很好的解决方案。但是,如果您对这两个存储桶具有不同的凭据,该怎么办?
Roee Gavirel 2014年

2
凭据用于执行复制命令。这些单一凭据需要在源/目标存储桶中具有适当的读/写权限。要在帐户之间进行复制,则需要使用存储桶策略,以允许从其他帐户的凭据访问存储桶。
马特·豪尔

9

如果您在AWS中拥有Unix主机,请使用s3tools.org中的s3cmd。设置权限,以便您的密钥成为对您的开发存储区的读取访问权限。然后运行:

s3cmd cp -r s3://productionbucket/feed/feedname/date s3://developmentbucket/feed/feedname

服务器端?s3没有服务器端。所有命令都是从远程客户端执行的。
dk。

顺便说一句,此命令在Internet上似乎工作正常!
加贝·科普利

3
“服务器端”问题有效。s3cmd传输会将所有数据分流到客户端,还是S3到S3的直接传输?如果是前者,则最好在AWS云中运行它,以避免外部WAN传输。
Bruce Edge

1
复制全部在S3上进行。
dk。

另请注意,如果您不小心中断了此过程s3cmd cp,则不接受该--skip-existing选项,但是可以s3cmd sync改用现有的跳过程序运行
ianstarz 2014年

9

对我来说,以下命令起作用了:

aws s3 mv s3://bucket/data s3://bucket/old_data --recursive

2
简单而直接的解决方案...如果可以使用aws cli完成此简单任务,为什么还要使用第三方工具或变通方法?
Fr0zenFyr

7

这是用于执行此操作的Ruby类: https //gist.github.com/4080793

用法示例:

$ gem install aws-sdk
$ irb -r ./bucket_sync_service.rb
> from_creds = {aws_access_key_id:"XXX",
                aws_secret_access_key:"YYY",
                bucket:"first-bucket"}
> to_creds = {aws_access_key_id:"ZZZ",
              aws_secret_access_key:"AAA",
              bucket:"first-bucket"}
> syncer = BucketSyncService.new(from_creds, to_creds)
> syncer.debug = true # log each object
> syncer.perform

5

实际上,从最近开始,我只是在AWS s3界面中使用copy + paste操作。只需导航到要复制的文件,单击“操作”->“复制”,然后导航到目标存储区,然后单击“操作”->“粘贴”

它可以非常快速地传输文件,并且看起来像是一个复杂的解决方案,不需要任何编程,也不需要诸如此类的顶级解决方案。


是。几分钟前我也发现了。我投票支持,所以更多的人可以节省时间:)
JCarlosR

我尝试在一个存储桶中复制包含134,364个对象的副本。花了几个小时。最终目的地只有134,333个文件-副本说它“成功”,但没有解释丢失的文件。
沃伦斯

使用此处其他文章中描述的“ aws s3 sync”类型命令,所有134,364个对象在大约20分钟内被复制。
沃伦斯,

4

我们在Snowplow的ETL作业遇到了这个确切的问题,因此我们将并行文件复制代码(Ruby,基于Fog构建)提取到了自己的Ruby gem中,称为Sluice:

https://github.com/snowplow/sluice

Sluice还处理S3文件的删除,移动和下载;全部并行化,并在操作失败时自动重试(它经常出奇地执行)。我希望它有用!



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.