问:线上的业务最怕什么?
答:误删除数据。
继续问:比误删除数据还可怕的是什么呢?
答:删除后无法找回!
COS对象存储有11个9的数据保障级别,但是不保障主动删除的数据,如果真是手欠清空了存储桶。那么真的是无法挽回了。
所以数据备份的事情,一定要防患于未然,提前做好高可用架构。COS产品官网上有详细的高可用架构说明文档https://cloud.tencent.com/document/product/436/37709
以上的理论内容,咱们就不详细说了。这里介绍一下,当真的手残点击了当前桶和备份桶的删除动作后,我们继续多版本的高可用架构如何可以快速的恢复我们想要的数据。
这里介绍一下快速恢复的方案。总结成一句话:遍历所有目标对象,找到第一个非删除版本的数据对象进行拷贝。
场景
- 第一条为删除标记,第二条为最新版本数据,第三条为次新版本数据。
- 第一条为最新版本数据。
- 第一条为最新版本数据,第二条为次新版本是数据。
- 第一条为删除标记,第二条为删除标记,第三条为最新版本数据,第四条为次新版本数据。
final int maxKeyNum = 400;
ListVersionsRequest listVersionsRequest = new ListVersionsRequest();
listVersionsRequest.withBucketName(srcbucket).withPrefix(keyPrefix).withMaxResults(maxKeyNum);
VersionListing versionListing = cossrcclient.listVersions(listVersionsRequest);
List < String > objectlist = new ArrayList < String > ();
int i = 0;
while (true) {
List < COSVersionSummary > versionSummaries = versionListing.getVersionSummaries();
for (COSVersionSummary versionInfo: versionSummaries) {
// 对相同可key的文件list出来的顺序是版本号由近到远
i ;
String versionId = versionInfo.getVersionId();
String key = versionInfo.getKey();
long expectedLength = versionInfo.getSize();
String expectedEtag = versionInfo.getETag();
Boolean islatest = versionInfo.isLatest();
Owner owner = versionInfo.getOwner();
String getStorageClass = versionInfo.getStorageClass();
Boolean isDeleteMarker = versionInfo.isDeleteMarker();
System.out.println("Id:" i); //ID
System.out.println("versionId:" versionId); //版本ID
System.out.println("key:" key); //对象全称
System.out.println("islatest:" islatest); //是否最新
System.out.println("isDeleteMarker:" isDeleteMarker); //是否有删除标记
System.out.println("expectedLength:" expectedLength); //对象大小
System.out.println("expectedEtag:" expectedEtag); //Etag值
System.out.println("Owner:" owner.getId() ":" owner.getDisplayName()); //资源拥有者ID和名称
System.out.println("getStorageClass:" getStorageClass); //对象类型
if (isDeleteMarker == false) //标记不是删除标记的记录
{
if (islatest == true) //标记是最新的记录
{
System.out.println("最新版文件,拷贝" "key:" key ",version:" versionId);
copyObjectRequest(cosdstclient, srcappid, srcbucket, key, versionId, dstbucket, key);
objectlist.add(key);
} else {
if (!copiedobject(key, objectlist)) {
System.out.println("次新文件,拷贝" "key:" key ",version:" versionId);
copyObjectRequest(cosdstclient, srcappid, srcbucket, key, versionId, dstbucket, key);
objectlist.add(key);
}
}
}
}
if (!versionListing.isTruncated()) {
break;
}
versionListing = cossrcclient.listNextBatchOfVersions(versionListing); //列出下一批版本
System.out.println("--------------------------------------");
}
这个方法的作用是,while每次400条遍历所有的目标对象。
1.当有DeleteMarker标记时则跳过操作。
2.当islastest为true时,说明这是一个最新版本的数据对象。则进行复制操作。
3.当既不是deletemarker标签,也不是islastest最新版时。我们会找到第一个数据对象,作为筛选后的最新版实体数据,进行复制。
4.复制操作完成后,对象名称加入objectlist,避免再次被覆盖,也就是说,每一个对象,最多只会操作一次复制。
通过这个逻辑,我们只要找到第一个有实体数据的对象,做复制操作,就可以实现所有最新版的复制功能,实现批量的数据恢复。
以下是已复制的object列表。
代码语言:javascript复制private static Boolean copiedobject(String object, List < String > objectlist) {
for (int i = 0; i < objectlist.size(); i ) {
//System.out.println("object:" object);
//System.out.println("objectlist.get(i):" objectlist.get(i));
if (object.equals(objectlist.get(i))) {
return true;
}
}
return false;
}
测试一下,我们做了一份桶的数据清单,如下
备份桶文件列表
这里模拟各种删除场景,之后执行批量恢复脚本,执行结果如下
脚本执行结果
完成后在目标桶查看
目标桶恢复的对象列表
验证成功。
java脚本文件:https://wainsun-1253985742.cos.ap-beijing.myzijiebao.com/脚本文件/DisasterRecovery.rar
python脚本链接:https://github.com/shezhangjun/TencentCOS/tree/master/Python_SDK/COS_Disaster_Recovery