通过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; }
测试一下,我们做了一份数据清单如下

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

目标桶查看

验证成功。
以上就是通过多版本的方式,批量快速的恢复被删除数据的方法。完整脚本见附件。
注:本方法目前只适合同账号恢复。不占用本地带宽资源,快速便捷。