具体的restoreSnapshot方法

好的,让我们详细分析 restoreSnapshot 方法。这个方法位于 SnapshotServiceImpl 类中,负责从快照中恢复指定的索引。以下是方法的详细分析:

方法签名

private void restoreSnapshot(String repositoryName, String snapshotName, List<String> indicesList, Date delTime, Long id) throws IOException {
  • 参数
    • repositoryName:快照仓库的名称。
    • snapshotName:快照的名称。
    • indicesList:需要恢复的索引列表。
    • delTime:删除时间。
    • id:记录的 ID,用于数据库操作。
  • 异常
    • IOException:如果在恢复过程中发生 I/O 错误,则抛出此异常。

方法逻辑

  1. 查询快照信息

    List<SnapshotInfo> snapshotInfoList = queryIndicesByRepoAndSnapshot(repositoryName, snapshotName);
    
    • 调用 queryIndicesByRepoAndSnapshot 方法查询指定仓库和快照的信息。
  2. 过滤索引列表

    if (!snapshotInfoList.isEmpty() && !snapshotInfoList.get(0).indices().isEmpty()) {
        List<String> snapshotIndicesList = snapshotInfoList.get(0).indices();
        indicesList = indicesList.stream().filter(snapshotInfo -> snapshotIndicesList.contains(snapshotInfo)).collect(Collectors.toList());
    }
    
    • 如果查询结果不为空且包含索引信息,则过滤 indicesList,只保留存在于快照中的索引。
  3. 检查索引是否存在

    if (!indicesList.isEmpty()) {
        List<String> notExistsIndicesList = indicesList.stream().filter(index -> !elasticSearchService.isIndexExist(index)).collect(Collectors.toList());
    
    • 进一步过滤 indicesList,只保留那些在 Elasticsearch 中不存在的索引。
  4. 记录恢复请求

    if (id == 0 && !notExistsIndicesList.isEmpty()) {
        IndicesRestoreRecord record = new IndicesRestoreRecord();
        record.setRepositoryName(repositoryName);
        record.setSnapshotName(snapshotName);
        record.setIndicesName(JSON.toJSONString(notExistsIndicesList));
        record.setIsSuccess(false);
        record.setDelTime(delTime);
        indicesRestoreRecordMapper.insert(record);
    }
    
    • 如果 id 为 0 且存在需要恢复的索引,则创建一个 IndicesRestoreRecord 记录,并将其插入数据库。
  5. 准备恢复对象

    for (String indices : notExistsIndicesList) {
        IndicesRestore restore = new IndicesRestore();
        restore.setId(null);
        restore.setDelFlag(0);
        restore.setDelTime(delTime);
        restore.setRestoredIndexName(indices + "_restored_" + LocalDate.now());
        restore.setRestoredTime(new Date());
        indicesRestores.add(restore);
    }
    
    • 为每个需要恢复的索引创建一个 IndicesRestore 对象,并添加到 indicesRestores 列表中。
  6. 构建恢复请求

    if (CollectionUtils.isNotEmpty(notExistsIndicesList)) {
        RestoreSnapshotRequest request = new RestoreSnapshotRequest(repositoryName, snapshotName);
        request.indices(notExistsIndicesList);
        log.info("索引:{}, 开始恢复。", notExistsIndicesList);
        Map<String, Object> map = Maps.newHashMap();
        map.put("index.lifecycle.name", null);
        request.indexSettings(map);
        request.renamePattern("(.+)");
        request.renameReplacement("$1_restored_" + LocalDate.now());
        request.waitForCompletion(true);
    
    • 构建 RestoreSnapshotRequest 对象,设置需要恢复的索引列表和其他配置。
    • 设置索引生命周期名称为 null,以便恢复后索引不再受生命周期管理。
    • 设置重命名模式和替换规则,以便恢复的索引名称带有 _restored_ 前缀。
    • 设置 waitForCompletiontrue,表示等待恢复操作完成。
  7. 异步监听恢复结果

    ActionListener<RestoreSnapshotResponse> listener = new ActionListener<RestoreSnapshotResponse>() {
        @Override
        public void onResponse(RestoreSnapshotResponse restoreSnapshotResponse) {
            log.info("快照恢复onResponse返回 {}", indicesRestores);
            for (IndicesRestore restore : indicesRestores) {
                indicesRestoreMapper.insert(restore);
            }
            // 更新回复成功记录
            String indicesName = JSON.toJSONString(notExistsIndicesList);
            Example example = new Example(IndicesRestoreRecord.class);
            example.createCriteria().andEqualTo("indicesName", indicesName);
            IndicesRestoreRecord indicesRestoreRecord = new IndicesRestoreRecord();
            indicesRestoreRecord.setIsSuccess(true);
            indicesRestoreRecordMapper.updateByExampleSelective(indicesRestoreRecord, example);
            log.info("快照恢复成功, [indicesList:{}]", indicesRestores);
        }
    
        @Override
        public void onFailure(Exception e) {
            AtomicBoolean flag = new AtomicBoolean(true);
            log.info("onFailure进入, 开始校验快照恢复索引是否存在。");
            indicesRestores.forEach(indicesRestore -> {
                log.info("校验索引{}, 是否存在。", indicesRestore.getRestoredIndexName());
                if (!elasticSearchService.isIndexExist(indicesRestore.getRestoredIndexName())) {
                    log.info("快照恢复, 索引:{}, 恢复失败。", indicesRestore.getRestoredIndexName());
                    flag.set(false);
                }
            });
            log.info("最终恢复结果:{}", flag.get());
            if (flag.get()) {
                for (IndicesRestore restore : indicesRestores) {
                    indicesRestoreMapper.insert(restore);
                }
                // 更新回复成功记录
                String indicesName = JSON.toJSONString(notExistsIndicesList);
                Example example = new Example(IndicesRestoreRecord.class);
                example.createCriteria().andEqualTo("indicesName", indicesName);
                IndicesRestoreRecord indicesRestoreRecord = new IndicesRestoreRecord();
                indicesRestoreRecord.setIsSuccess(true);
                indicesRestoreRecordMapper.updateByExampleSelective(indicesRestoreRecord, example);
                log.info("快照恢复成功, [indicesList:{}]", indicesRestores);
            }
        }
    };
    restHighLevelClient.snapshot().restore(request, RequestOptions.DEFAULT, listener);
    
    • 创建一个 ActionListener 监听恢复操作的结果。
    • onResponse 方法中,记录恢复成功的索引,并更新数据库中的记录。
    • onFailure 方法中,校验恢复的索引是否存在,如果所有索引都恢复成功,则更新数据库中的记录。

总结

restoreSnapshot 方法的主要功能是从快照中恢复指定的索引,并记录恢复过程中的各种状态。具体步骤包括:

  1. 查询快照信息。
  2. 过滤需要恢复的索引。
  3. 记录恢复请求。
  4. 准备恢复对象。
  5. 构建恢复请求。
  6. 异步监听恢复结果,并更新数据库记录。

这个方法通过详细的步骤和异常处理,确保了快照恢复操作的可靠性和可追溯性。

posted @ 2024-11-21 10:26  一曲微茫  阅读(1)  评论(0编辑  收藏  举报