如何在amazonS3上检查两个大文件是否相同



我需要用boto将amazon S3上的大文件(>5GB)从同一个bucket中移动到同一个bucket中。为此,我需要使用多部分API,它不使用md5和etag。

虽然我认为(只有98%的把握)我的代码是正确的,但我想在删除原始代码之前验证新副本是否损坏。然而,除了下载这两个对象并在本地进行比较外,我找不到任何方法,这对于5GB+文件来说是一个相当长的过程。

为了记录在案,下面是我用boto复制一个大文件的代码,也许这可以帮助一些人。如果我的问题没有好的解决方案,也许有人会发现一个错误,阻止我破坏数据。

import boto
copy_size = 1000000000  #1e9
bucket_name = 'mybucket'
orig_key_name = 'ABigFile'
dest_key_name = 'ABigFile.clone'
s3 = boto.connect_s3()
mybucket = s3.get_bucket(bucket_name)
key = mybucket.get_key(orig_key_name)
mp = mybucket.initiate_multipart_upload(dest_key_name)  #keyname
print 'key size: ', key.size
count = 1 
start = 0
end = -1
while end < key.size-1:
   print 'count: ', count
   start = end + 1 
   end = min( key.size -1 , start + copy_size )
   mp.copy_part_from_key(bucket_name, orig_key_name, count , start, end )
   count+=1
mp.complete_upload()

此代码仅适用于大于等于5368709121字节的原始密钥。

您应该能够在数据流上计算SHA-1哈希(请参阅此SO线程中的C++代码,它可以为python方法提供提示)。通过将散列数据流重定向到等效的/dev/null,您应该能够比较两个文件的SHA-1散列,而无需首先在本地下载它们。

如果不知道AWS如何计算多部分上传的etag,就无法执行您想要的操作。如果您有对象的本地副本,则可以计算在本地对象上复制的每个部分的md5,并将其与每个mp.copy_part_from_key()返回的键中的etag进行比较。听起来你没有本地对象。

你还有一个隐藏在僵尸中的小问题,可能会也可能不会导致你在极少数情况下丢失数据。如果你查看boto源代码,你会注意到mp.complete_upload()函数在上传时实际上没有为AWS返回的任何部分使用任何etag。当您使用multipart_complete时,它实际上会自己创建一个全新的多部分列表,并从S3中获得一个新的部分和etag列表。这是有风险的,因为最终的一致性和列表可能是完整的,也可能不是完整的。理想情况下,multipart_complete()应该使用每个远程副本返回的etags和部件信息,以确保完全安全。这是亚马逊在其文档中建议的(请参阅Multipart Upload Listings下的注释)。

也就是说,如果确认两个对象的文件大小相同,问题就不太可能出现。我认为最糟糕的情况是,一个部分没有在多部分上传列表中列出。列出的零件本身不应该是错误的。

最新更新