具體的restoreSnapshot方法

一曲微茫發表於2024-11-21

好的,讓我們詳細分析 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. 非同步監聽恢復結果,並更新資料庫記錄。

這個方法透過詳細的步驟和異常處理,確保了快照恢復操作的可靠性和可追溯性。

相關文章