本文介绍同账号和跨账号下(包括同区域和跨区域)的数据复制常见问题以及排查方法。
为什么无法创建数据复制规则?
排查是否缺少必要权限。
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。
无地域属性Bucket跨区域复制是否收费?
收费。无地域属性Bucket进行跨区域复制时也会产生跨区域流量费用、请求费用等费用。