【问题标题】:How do I only copy missing objects between buckets using ruby aws-sdk?如何仅使用 ruby​​ aws-sdk 在存储桶之间复制丢失的对象?
【发布时间】:2013-10-04 03:58:40
【问题描述】:

我编写了一个脚本来将 s3 对象从我的生产 s3 存储桶复制到我的开发存储桶,但是运行需要很长时间,因为我在复制之前单独检查每个对象是否存在。有没有办法区分两个桶并只复制我需要的对象?还是将存储桶作为一个整体进行复制?

这是我目前拥有的:

count = 0
puts "COPYING FROM #{prod_bucket} to #{dev_bucket}"
bm = Benchmark.measure do 
  AWS::S3.new.buckets[prod_bucket].objects.each do |o|
    exists = AWS::S3.new.buckets[dev_bucket].objects[o.key].exists?

    if exists
      puts "Skipping: #{o.key}"
    else
      puts "Copy: #{o.key} (#{count})"
      o.copy_to(o.key, :bucket_name => dev_bucket, :acl => :public_read)
      count += 1
    end
  end
end
puts "Copied #{count} objects in #{bm.real}s"

【问题讨论】:

    标签: ruby amazon-s3


    【解决方案1】:

    我从未使用过该 gem,但您的代码看起来可以接收一个数组,其中所有项目都存储在存储桶中。为两个存储桶加载该列表,并使用简单的数组操作确定丢失的文件。应该快得多。

    # load file lists (looks up objects in batches of 1000)
    source_files  = AWS::S3.new.buckets[prod_bucket].objects.map(&:key)
    target_files  = AWS::S3.new.buckets[dev_bucket].objects.map(&:key)
    
    # determine files missing in dev
    files_to_copy = source_files - target_files
    files_to_copy.each_with_index do |file_name, i|
      puts "Coping #{i}/#{files_to_copy.size}: #{file_name}"
    
      S3Object.store(file_name, 
                     S3Object.value(file_name, PROD_BUCKET_NAME), 
                     DEV_BUCKET_NAME)
    end
    
    # determine files on dev that are not existing on prod
    files_to_remove = target_files - source_files
    files_to_remove.each_with_index do |file_name, i|
      puts "Removing #{i}/#{files_to_remove.size}: #{file_name}"
    
      S3Object.delete(file_name, DEV_BUCKET_NAME)
    end
    

    【讨论】:

    • 不幸的是,虽然 'objects' 看起来像是一个数组,但它实际上只是一个实现 enumerable 的包装器,因此您可以遍历对象。我猜他们这样做是因为你可以在一个桶里有这么多的对象。我想我有大约 70k 个对象。计数也很困难,因为调用 .count 还必须枚举每个对象:(
    • 每个 S3 对象都有一个表示其文件名的键。我更新了我的代码示例。请看一看。
    • 每次迭代或调用 exsits? 都必须向亚马逊发出 http 请求,所以我相信您的解决方案将花费与我目前所拥有的时间大致相同的时间,它只会花费大部分时间在前 2 行,而不是每次循环吃两次 http 调用。
    • 请再次阅读我更新的代码。前两行只有两个请求——即使每个存储桶中有数千个文件。没有检查是否存在,因为buckets.objects 只会返回现有文件。
    • 所以看起来你正在做某事 :) 在运行前 2 行时查看日志,gem 足够聪明,可以批量查找 1000 个,所以不是 1 个 http 请求,但很多每个对象优于 1 个。看起来这会很好,谢谢!
    猜你喜欢
    • 1970-01-01
    • 2016-11-05
    • 2011-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-12
    • 1970-01-01
    • 2017-07-13
    相关资源
    最近更新 更多