2012-02-10 17 views
1

我需要將amazon S3上的大文件(> 5GB)與boto一起移動到同一個存儲桶中。爲此,我需要使用multipart API,它不使用md5作爲etags的總和。如何檢查亞馬遜S3上的兩個大文件是否相同?

儘管我認爲(只有98%肯定)我的代碼是正確的,但我想驗證新副本在刪除原始文件之前是否損壞。但是我找不到任何方法,除了下載這兩個對象並在本地進行比較,對於5GB +文件來說這是一個相當長的過程。

爲了記錄,以下是我的代碼複製一個大的文件與博託,也許這可以幫助某人。如果我的問題沒有好的解決方案,也許有人會發現一個錯誤,並防止我破壞數據。

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字節。

+0

測試兩個小~1kB文件。 – istruble 2012-02-11 00:02:52

+1

@istruble:好吧,多部分只適用於5BM +塊。但是,我仍然只能測試幾個文件,並希望亞馬遜部分沒有任何錯誤,並且我的測試是詳盡的。 – ascobol 2012-02-11 08:20:58

+0

謝謝。我今天學了些新東西。 – istruble 2012-02-13 16:49:47

回答

1

您應該能夠計算數據流上的SHA-1散列(C++代碼see this SO thread,它可以提供python方法的提示)。通過將您的散列數據流重定向到/dev/null,您應該能夠比較兩個文件的SHA-1哈希值,而無需先在本地下載它們。

+0

我懷疑這將與亞馬遜S3遠程工作... – ascobol 2012-02-11 08:10:42

+0

你只是下載數據來計算散列,但不存儲數據。就任何給定的程序而言,S3只是另一個數據源,可通過Web請求訪問。 – 2012-02-11 08:14:34

+0

我明白了,是時候嘗試EC2了:) – ascobol 2012-02-11 08:30:55

0

如果不知道AWS如何計算分段上傳的etag,沒有辦法做到您想要的。如果您有對象的本地副本,則可以計算要在本地對象上覆制的每個零件的md5,並將其與每個mp.copy_part_from_key()返回的關鍵點中的etag進行比較。聽起來像你沒有本地對象,但。

您還有一個隱藏在boto中的小型非顯而易見的問題,可能會或可能不會導致您在非常罕見的情況下丟失數據。如果您查看boto源代碼,您會注意到,mp.complete_upload()函數實際上並未使用AWS上傳時返回的任何零件的任何etags。當您使用multipart_complete時,它實際上會自行創建一個全新的多部分列表,並從S3中獲取零件和etags的新列表。這是有風險的,因爲最終的一致性,列表可能會或可能不完整。 multipart_complete()理想情況下應該使用每個遠程副本返回的etags和部分信息是完全安全的。這是亞馬遜在其文檔中建議的(請參閱Multipart Upload Listings下的註釋)。

也就是說,如果確認兩個對象的文件大小相同,那麼出現問題的可能性就會降低。我認爲最糟糕的情況是部分內容未列入分段上傳列表中。列出的部分本身不應該是不正確的。