本文介紹同帳號和跨帳號下(包括同地區和跨地區)的資料複製常見問題以及排查方法。
為什麼無法建立資料複製規則?
排查是否缺少必要許可權。
RAM使用者權限缺失
RAM使用者通過控制台的方式建立資料複製規則時,無法單擊確定
問題原因:缺少oss:PutBucketReplication許可權。
解決方案:為RAM使用者授予oss:PutBucketReplication許可權。
RAM使用者通過控制台的方式建立資料複製規則時,授權角色不顯示自訂建立的角色
問題原因:缺少ram:ListRoles許可權。
解決方案:為RAM使用者授予ram:ListRoles許可權。
具體步驟,請參見為RAM使用者授權自訂的權限原則。
RAM角色許可權缺失
檢查Bucket版本控制狀態是否一致。
開啟資料同步的源Bucket和目標Bucket的版本控制狀態必須一致,即這兩個Bucket同時處於未開啟或者已開啟版本控制。
填寫的Endpoint或者AccessKey資訊是否正確。
通過SDK或者ossutil等方式建立資料複製規則時,需要檢查以下配置:
檢查用於建立複製關係的源Bucket以及目標Bucket所在地區的Endpoint是否正確。更多資訊,請參見OSS地區和訪問網域名稱。
檢查用於建立複製關係的AccessKey是否正確。更多資訊,請參見查看RAM使用者的AccessKey資訊。
為什麼資料沒有複製到目標Bucket?
在源Bucket配置了資料複製規則後,如果Object副本未出現在目標Bucket中,請參考以下幾種可能原因排查並修複問題。
源Bucket配置是否正確。
資料複製狀態是否為已開啟(Enabled)。
首碼(Prefix)是否正確。
同步指定Object:如果需要同步源Bucket中的指定Object到目標Bucket,請將Prefix設定為指定檔案首碼。例如,Prefix設定為log,則僅複製log/date1.txt、log/date2.txt等以log開頭的Object。與指定Prefix不匹配的Object不會複製到目標Bucket,例如date3.txt。
說明填寫的檔案首碼末尾不能添加星號(*),例如log/*,也不能包含Bucket名稱。
同步所有Object:如果需要將源Bucket中的全部Object複製到目標Bucket,請將Prefix置空。
確認是否配置複製歷史檔案,是否是歷史檔案沒有同步。
確認源Bucket中的檔案是否是從其他Bucket中使用同地區或者跨地區複製過來的。
如果Bucket中的某個Object是另一個複製配置建立的副本,則OSS不會複製該Object。例如,您配置了Bucket A同步到Bucket B,Bucket B再同步到Bucket C,則OSS不會將從Bucket A同步到Bucket B的Object副本複製到Bucket C。
確認檔案是否是KMS加密。如果是KMS加密的,需要選擇複製KMS加密對象複製。
在源Object或者目標Bucket使用了KMS託管祕密金鑰加密方式(即SSE-KMS,指定CMK ID)的情況下,要將Object複製到目標Bucket,則必須選中複製,並配置以下參數:
使用的KMS密鑰:為目標Object指定加密的KMS密鑰。
您需要提前在KMS平台建立一個與目標Bucket相同地區的KMS密鑰。具體操作,請參見建立密鑰。
授權角色:授權一個RAM角色對目標Object執行KMS加密操作。
建立角色:建立RAM角色對目標Object執行KMS加密,角色名稱格式為
kms-replication-源Bucket名稱-目標Bucket名稱
。AliyunOSSRole:使用AliyunOSSRole角色對目標Object執行KMS加密。若您之前未建立AliyunOSSRole角色,當您選擇此項時,OSS將自動建立AliyunOSSRole角色。
說明如果是您建立的角色或者修改角色許可權時,請確保授予角色
AliyunOSSFullAccess
的許可權,否則可能導致資料無法複製。
您可以通過HeadObject和GetBucketEncryption分別查詢源Object和目標Bucket的加密狀態。
查看複製進度是否為100%。
資料複製採用非同步(近即時)複製的機制,將資料複製到目標Bucket需要一定的時間,通常幾分鐘到幾小時不等,取決於資料的大小。如果要複製的Object較大,請稍等片刻。待確認資料複製進度達到100%後,再檢查Object是否出現在目標Bucket中。
為什麼目標Bucket沒有同步刪除資料?
原因1:目標Bucket建立了保留原則(WORM)。
在保留原則的保留周期到期之前,任何使用者(包括資源擁有者)均不能刪除該Bucket中的Object。
原因2:目標Bucket是否刪除資料取決於源Bucket的版本控制狀態以及配置的資料複製策略。
源Bucket版本控制狀態
請求方式
資料複製策略
結果
未開啟版本控制
發起Delete請求
增/改同步
只刪除源Bucket的Object,不刪除目標Bucket的Object。
增/刪/改同步
同步刪除源和目標Bucket的Object。
已開啟版本控制
發起Delete請求但未指定Object版本ID
增/改同步
源和目標Bucket均不刪除Object,OSS會在源Bucket中建立刪除標記(Delete Marker),且源Bucket建立的刪除標記會同步到目標Bucket。
增/刪/改同步
發起Delete請求且指定了Object版本ID
增/改同步
只刪除源Bucket內的Object,不刪除目標Bucket內的Object。
增/刪/改同步
同步刪除源和目標Bucket的Object。
如何驗證複製完成後目標Bucket與源Bucket的資料是否一致?
您可以通過以下代碼驗證複製完成後目標Bucket與源Bucket的資料一致性。
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.model.*;
import com.aliyun.oss.OSSException;
import com.aliyuncs.exceptions.ClientException;
public class Demo {
public static void main(String[] args) throws ClientException {
// 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// srcEndpoint填寫Bucket所在地區對應的Endpoint。
String srcEndpoint = "https://oss-cn-hangzhou.aliyuncs.com";
OSSClient srcClient = new OSSClient(srcEndpoint , credentialsProvider);
// 填寫源Bucket名稱。
String srcBucketName = "src-replication-bucket";
// destEndpoint填寫Bucket所在地區對應的Endpoint。
String destEndpoint = "https://oss-cn-beijing.aliyuncs.com";
OSSClient destClient = new OSSClient(destEndpoint, credentialsProvider);
// 填寫目標Bucket名稱。
String destBucketName = "dest-replication-bucket";
// 源Bucket與目標Bucket處於非版本控制狀態時,通過listObjectsV2列舉源Bucket被複製的檔案。
// 源Bucket與目標Bucket處於開啟或暫停版本控制狀態時,通過listVersions列舉源Bucket被複製的檔案。
ListObjectsV2Result result;
ListObjectsV2Request request = new ListObjectsV2Request(srcBucketName);
do {
result = srcClient.listObjectsV2(request);
for (OSSObjectSummary summary : result.getObjectSummaries())
{
String objectName = summary.getKey();
ObjectMetadata srcMeta;
try {
// 擷取源Bucket被複製檔案的中繼資料。
srcMeta = srcClient.headObject(srcBucketName, objectName);
} catch (OSSException ossException) {
if (ossException.getErrorCode().equals("NoSuchKey")) {
continue;
} else {
System.out.println("head src-object failed: " + objectName);
}
continue;
}
ObjectMetadata destMeta;
try {
// 擷取複製到目標Bucket的檔案中繼資料。
destMeta = destClient.headObject(destBucketName, objectName);
} catch (OSSException ossException) {
if (ossException.getErrorCode().equals("NoSuchKey")) {
System.out.println("dest-object not exist: " + objectName);
} else {
System.out.println("head dest-object failed: " + objectName);
}
continue;
}
// 檢查源Bucket與目標Bucket複製檔案的CRC是否一致。
Long srcCrc = srcMeta.getServerCRC();
String srcMd5 = srcMeta.getContentMD5();
if (srcCrc != null) {
if (destMeta.getServerCRC() != null) {
if (!destMeta.getServerCRC().equals(srcCrc)) {
System.out.println("crc not equal: " + objectName
+ " | srcCrc: " + srcCrc + " | destCrc: " + destMeta.getServerCRC());
}
continue;
}
}
// 檢查源Bucket與目標Bucket複製檔案的MD5是否一致。
if (srcMd5!= null) {
if (destMeta.getContentMD5() != null) {
if (!destMeta.getContentMD5().equals(srcMd5)) {
System.out.println("md5 not equal: " + objectName
+ " | srcMd5: " + srcMd5 + " | destMd5: " + destMeta.getContentMD5());
}
continue;
}
}
// 檢查源Bucket與目標Bucket複製檔案的ETag是否一致。
if (srcMeta.getETag() == null || !srcMeta.getETag().equals(destMeta.getETag())) {
System.out.println("etag not equal: " + objectName
+ " | srcEtag: " + srcMeta.getETag() + " | destEtag: " + destMeta.getETag());
}
}
request.setContinuationToken(result.getNextContinuationToken());
request.setStartAfter(result.getStartAfter());
} while (result.isTruncated());
}
}
是否支援複製傳遞?
不支援。例如,Bucket A配置了到Bucket B的資料複製規則,Bucket B配置了到Bucket C的資料複製規則,則Bucket A的資料僅複製到Bucket B,不會複製到Bucket C。
如果要將Bucket A的資料複製到Bucket C,則您還需要為Bucket A配置到Bucket C的資料複製規則。
如果Bucket A和Bucket B同時開啟了複製歷史資料,在歷史資料複製未完成時,可能存在新寫入Bucket A的資料被歷史複製的任務掃描到,從而複製到Bucket C中。
OSS Bucket雙向同步是否會有迴圈複製的風險?
不會有風險。Bucket A與Bucket B之間配置雙向複製關係後,通過複製關係從Bucket A到Bucket B的資料(包括新增和歷史資料),不會再次從Bucket B複製到Bucket A。同理,通過複製關係從Bucket B到Bucket A的資料(包括新增和歷史資料),不會再次從Bucket A複製到Bucket B。
源Bucket通過生命週期規則指定刪除的檔案,目標Bucket是否會同步刪除這些檔案?
源Bucket資料複製策略指定為增/改 同步,則源Bucket通過生命週期規則指定刪除的檔案,目標Bucket不會同步刪除這些檔案。
源Bucket資料複製策略指定為增/刪/改 同步,則源Bucket通過生命週期規則指定刪除的檔案,目標Bucket也會同步刪除這些檔案。
說明如果您在目標Bucket仍然可以找到源Bucket通過生命週期指定刪除的檔案,並非是增/刪/改 同步的資料複製策略不生效,可能是您通過目標Bucket手動寫入了與源Bucket刪除的同名檔案。
為什麼歷史資料複製進度長時間顯示為0%?
複製進度並非即時更新
歷史資料複製進度並非即時更新,需要等待所有檔案掃描完成後才會複製更新。如果您Bucket內的檔案數量較多(例如達到上億層級),則可能需要等待數小時才會更新歷史資料複製進度。歷史資料複製進度未更新,並不代表歷史資料沒有複製到目標Bucket。
您可以通過查看目標Bucket的儲存容量以及複製流入和流出流量產生的變化,確認源Bucket內的歷史資料是否已開始複製到目標Bucket。關於查看目標Bucket的儲存容量以及複製流入和流出流量的具體步驟,請參見查詢Bucket層級的用量情況。
源Bucket的授權策略有誤
建立資料複製規則目前不檢測源Bucket的授權策略,導致複製規則可以正常建立,但是資料並不會複製到目標Bucket,即資料複製進度為0。
配置正確的權限原則,請參見資料複製許可權介紹。
資料複製速度慢怎麼辦?
提升頻寬
資料複製採用非同步(近即時)機制,將資料從源Bucket傳輸到目標Bucket的過程可能需要幾分鐘到幾小時,具體時間取決於資料量的大小。如果複製過程耗時過長,建議檢查是否存在頻寬節流設定導致的複製任務延遲。如果確認為頻寬問題,建議聯絡支援人員申請提升頻寬,以最佳化複製效率。
開啟資料複製時間控制(RTC)
開啟RTC後,OSS會在幾秒內複製您上傳到OSS的大多數Object,並在10分鐘內複製99.99%的Object。開啟RTC後,OSS將針對開啟RTC的複製任務產生的資料複製流量收取費用。更多資訊,請參見使用資料複製時間控制(RTC)。
怎麼知道源Bucket和目標Bucket執行了哪些資料複製操作?
您可以通過在事件通知規則中,將事件類型配置為ObjectReplication:ObjectCreated
、ObjectReplication:ObjectRemoved
以及ObjectReplication:ObjectModified
的方式,擷取資料複製過程中源Bucket以及目標Bucket內Object的新增、更新、刪除、覆蓋等變化情況。詳情請參見通過事件通知即時處理OSS檔案變動。
暫停版本控制狀態下的Bucket是否支援資料複製?
不支援。僅允許對同時處於非版本化或開啟版本控制狀態的兩個Bucket開啟資料複製。
如果目標Bucket採用KMS加密,是否收取KMS加密的密碼編譯演算法API費用?
如果目標Bucket採用KMS加密,會收取KMS加密的密碼編譯演算法API費用。費用詳情,請參見KMS計費說明。
開啟資料複製後,是否支援關閉?
支援。您可以通過單擊規則右側的關閉複製來停止資料複製。
關閉複製後,已複製的資料將被保留在目標Bucket中,源Bucket中的增量資料將不再複製到目標Bucket。