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

  • 2020 年 3 月 31 日
  • 筆記

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

答:丢数据。

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

答:丢的干干净净,还无法找回!

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列表。

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;  }

测试一下,我们做了一份数据清单如下

备份桶文件列表

这里模拟各种删除场景,之后执行批量恢复脚本,执行结果如下

脚本执行结果

目标桶查看

目标桶恢复的对象列表

验证成功。

以上就是通过多版本的方式,批量快速的恢复被删除数据的方法。完整脚本见附件。

注:本方法目前只适合同账号恢复。不占用本地带宽资源,快速便捷。