通过COS多版本功能快速批量恢复数据

2023-05-11 17:43:33 浏览数 (2)

问:线上的业务最怕什么?

答:误删除数据。

继续问:比误删除数据还可怕的是什么呢?

答:删除后无法找回!

COS对象存储有11个9的数据保障级别,但是不保障主动删除的数据,如果真是手欠清空了存储桶。那么真的是无法挽回了。

所以数据备份的事情,一定要防患于未然,提前做好高可用架构。COS产品官网上有详细的高可用架构说明文档https://cloud.tencent.com/document/product/436/37709

以上的理论内容,咱们就不详细说了。这里介绍一下,当真的手残点击了当前桶和备份桶的删除动作后,我们继续多版本的高可用架构如何可以快速的恢复我们想要的数据。

这里介绍一下快速恢复的方案。总结成一句话:遍历所有目标对象,找到第一个非删除版本的数据对象进行拷贝。

场景

  • 第一条为删除标记,第二条为最新版本数据,第三条为次新版本数据。
  • 第一条为最新版本数据。
  • 第一条为最新版本数据,第二条为次新版本是数据。
  • 第一条为删除标记,第二条为删除标记,第三条为最新版本数据,第四条为次新版本数据。
代码语言:javascript复制
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

0 人点赞