好的,讓我們詳細分析 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 錯誤,則丟擲此異常。
方法邏輯
-
查詢快照資訊:
List<SnapshotInfo> snapshotInfoList = queryIndicesByRepoAndSnapshot(repositoryName, snapshotName);
- 呼叫
queryIndicesByRepoAndSnapshot
方法查詢指定倉庫和快照的資訊。
- 呼叫
-
過濾索引列表:
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
,只保留存在於快照中的索引。
- 如果查詢結果不為空且包含索引資訊,則過濾
-
檢查索引是否存在:
if (!indicesList.isEmpty()) { List<String> notExistsIndicesList = indicesList.stream().filter(index -> !elasticSearchService.isIndexExist(index)).collect(Collectors.toList());
- 進一步過濾
indicesList
,只保留那些在 Elasticsearch 中不存在的索引。
- 進一步過濾
-
記錄恢復請求:
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
記錄,並將其插入資料庫。
- 如果
-
準備恢復物件:
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
列表中。
- 為每個需要恢復的索引建立一個
-
構建恢復請求:
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_
字首。 - 設定
waitForCompletion
為true
,表示等待恢復操作完成。
- 構建
-
非同步監聽恢復結果:
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
方法的主要功能是從快照中恢復指定的索引,並記錄恢復過程中的各種狀態。具體步驟包括:
- 查詢快照資訊。
- 過濾需要恢復的索引。
- 記錄恢復請求。
- 準備恢復物件。
- 構建恢復請求。
- 非同步監聽恢復結果,並更新資料庫記錄。
這個方法透過詳細的步驟和異常處理,確保了快照恢復操作的可靠性和可追溯性。