snapshot源代码
@ Service("snapshotService")
@Slf4j
public class SnapshotServiceImpl implements SnapshotService {
@ Autowired
private RestHighLevelClient restHighLevelClient;
@ Autowired
private ElasticSearchServiceelasticSearchService;
@ Autowired
private IndicesRestoreMapper indicesRestoreMapper;
@ Autowired
private IndicesRestoreRecordMapper indicesRestoreRecordMapper;
//此方法用于检查给定名称的存储库是否存在于Elasticsearch中。它首先创建一个GetRepositoriesRequest对象,并设置需要查询的存储库名称。然后使用RestHighLevelClient发送请求到Elasticsearch以获取存储库信息。如果响应中的存储库列表非空,则表示该存储库存在,方法返回true;否则返回false。
public boolean isRepositoryExists( String repositoryName) throws IOException{
GetRepositoriesRequest repositoriesRequest= new GetRepositoriesRequest();
repositoriesRequest. repositories( new String[]{repositoryName});
boolean flag= false;
GetRepositoriesResponse repositoriesResponse =
restHighLevelClient. snapshot(). getRepository(repositoriesRequest,
RequestOptions. DEFAULT);
if (repositoriesResponse. repositories() != null&& !repositoriesResponse. repositories(). isEmpty()) {
flag= true;
)
return flag;
}
//此方法用于恢复多个快照中的索引。它接收一个包含多个快照信息的请求对象,遍历每个快照并尝试恢复其索引。通过调用 restoreSnapshot 方法逐个恢复快照,并根据恢复结果设置响应对象的状态。如果在恢复过程中发生 IOException,会记录错误日志并设置响应对象的状态为失败。
@ Override
public RestoreSnapshotIndicesResponse
restoreSnapshotIndices(RestoreSnapshotIndicesRequest request){
RestoreSnapshotIndicesResponse response = new RestoreSnapshotIndicesResponse();
if ( request == null || request. getSnapShotList()== null ||
request. getSnapShotList(). isEmpty()){
throw new TitanException("所传参数为空!");
}
List
for (SnapShotDTO snapShotDTO:snapShotDTOList){
try{
restoreSnapshot(snapShotDTO. getRepositoryName(), snapShotDTO. getSnapshotName(), snapShotDTO. getIndices(), snapShotDTO. getDelDate(), 0l);
response. setSuccess(0);
} catch (IOException ioe){
log. error("索引恢复发生异常,[快照名:{}] [RepositoryName:{}] [ indices:{}]",snapShotDTO. getSnapshotName(), snapShotDTO. getRepositoryName(),snapShotDTO. getIndices(), ioe);
response. setSuccess(-1);
}
}
return response;
}
//这是一个核心业务逻辑方法,负责从快照恢复索引。方法接收一个包含多个快照信息的请求对象。对于每个快照,调用私有方法restoreSnapshot尝试恢复对应的索引。如果所有快照都成功恢复,则在响应对象中设置成功标志;如果过程中遇到任何错误,则捕获异常并记录错误信息,同时在响应对象中设置失败标志。
private void restoreSnapshot( String repositoryName, String snapshotName, List< String> indicesList, Date delTime, Long id) throws IOException {
List
List
queryIndicesByRepoAndSnapshot(repositoryName, snapshotName);
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());
if(!indicesList. isEmpty()){
List< String>notExistsIndicesList= indicesList. stream(). filter( index - >!elasticSearchService. isIndexExist( index)
). collect( Collectors. toList());
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);
}
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);
}
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);
ActionListener
@ Override
public void onResponse(RestoreSnapshotResponserestoreSnapshotResponse){
log.info ("快照恢复onResponse 返回 “ ,indicesRestores);
for (IndicesRestore restore: indicesRestores){
indicesRestoreMapper. insert( restore);
}
//更新回复成功记录
String indicesName =
JSON. toJSONString(notExistsIndicesList);
Example example = newExample(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);
} else{
log. error("快照恢复出现异常[indicesList:{}]",indicesRestores, e);
throw new TitanException("快照恢复出现异常");
)
)
};
restHighLevelClient. snapshot(). restoreAsync( request, RequestOptions. DEFAULT, listener);
}
} else{
log. error("传入待恢复的索引列表:{}在快照备份中不存在!",indicesList);
throw new TitanException("传入待恢复的索引列表在快照备份中不存在!");
)
}
}
//此方法用于查询指定存储库和快照中的索引列表,并将结果封装到响应对象中返回。通过参数校验、查询快照信息、提取索引列表、设置响应对象和异常处理来完成查询操作。如果在查询过程中发生 IOException,会记录错误日志并抛出异常。
@ Override
public QueryIndicesByRepoAndSnapshotResponse
queryIndicesByRepoAndSnapshot(QueryIndicesByRepoAndSnapshotRequest request){
QueryIndicesByRepoAndSnapshotResponse response = new QueryIndicesByRepoAndSnapshotResponse();
if ( request == null || StringUtils. isBlank( request. getRepositoryName()) ||StringUtils. isBlank( request. getSnapshotName())){
throw new TitanException("传入参数不可为空");
}
try{
List
queryIndicesByRepoAndSnapshot( request. getRepositoryName(),
request. getSnapshotName());
List< String> indices= new ArrayList<>();
for (SnapshotInfo info:snapshotInfoList){
for ( String indicesName: info. indices()) {
indices. add(indicesName);
}
}
response. setIndicesList( indices);
log.info ("查询索引快照成功{}",indices);
} catch (IOException e){
log. error(" 查 询 索 引 快 照 异 常 [ repository:{}] [ snapshot:{}]", request. getRepositoryName(), request. getSnapshotName(),e);
throw new TitanException("查询索引快照异常!");
}
return response;
}
//此方法用于查询指定存储库和快照中的特定索引列表,并将结果封装到响应对象中返回。
@ Override
public QueryIndicesByRepoAndSnapshotWithIndicesResponse queryIndicesByRepoAndSnapshotWithIndices(QueryIndicesByRepoAndSnapshotWithIndicesRequest request){
QueryIndicesByRepoAndSnapshotWithIndicesResponse response = new QueryIndicesByRepoAndSnapshotWithIndicesResponse();
if ( request == null || StringUtils. isBlank( request. getRepositoryName()) ||StringUtils. isBlank( request. getSnapshotName())
ll request. getIndicesNameList() == null ll
request. getIndicesNameList(). isEmpty()){
throw new TitanException("传入参数不可为空");
}
try{
List
queryIndicesByRepoAndSnapshot( request. getRepositoryName(),
request. getSnapshotName());
List< String> indices= new ArrayList<>();
List< String>indicesList= new ArrayList<>();
request. getIndicesNameList(). forEach(indicesName->{
indicesList. add(indicesName. replace("*", ""));
});
List< String>snapIndexList=snapshotInfoList. get(0). indices();
for ( String indicesName:snapIndexList){
for ( String nIndicesName:indicesList){
if (indicesName. contains(nIndicesName)){
indices. add(indicesName);
break;
}
}
}
response. setIndicesList( indices);
log.info ("查询索引快照成功{}",indices);
} catch (IOExceptione){
log. error(" 查 询 索 引 快 照 异 常 [ repository:{}] [ snapshot:{}]",
request. getRepositoryName(), request. getSnapshotName(),e);
throw new TitanException("查询索引快照异常!");
}
return response;
}
//querySnapshotByRepo 方法用于查询指定存储库中的所有快照名称,并将结果封装到响应对象中返回。通过参数校验、查询快照列表、设置响应对象和异常处理来完成查询操作。
@ Override
public QuerySnapshotByRepoResponse
querySnapshotByRepo(QuerySnapshotByRepoRequest request){
QuerySnapshotByRepoResponse repoResponse = new QuerySnapshotByRepoResponse();
if ( request== null|| StringUtils. isBlank( request. getRepositoryName())){
throw new TitanException("参数不可为空");
}
try{
repoResponse. setSnapshotNameList(querySnapshotByRepo( request. getRepositoryName()));
} catch (IOException e){
log. error(" 查 询 索 引 快 照 异 常 , [ repository:{}]",
request. getRepositoryName(), e);
throw new TitanException("查询快照列表异常");
}
return repoResponse;
}
private List
GetSnapshotsRequest request= new GetSnapshotsRequest();
request. repository(repositoryName);
request. snapshots( new String[]{snapshotName});
GetSnapshotsResponse response = restHighLevelClient. snapshot(). get( request, RequestOptions. DEFAULT);
return response. getSnapshots();
}
private List< String> querySnapshotByRepo( String repositoryName) throwsIOException {
GetSnapshotsRequest request = new GetSnapshotsRequest();
request. repository(repositoryName);
GetSnapshotsResponse response = restHighLevelClient. snapshot(). get( request, RequestOptions. DEFAULT);
List< String> list= Lists. newArrayList();
->
response. getSnapshots(). stream(). filter(snapshotInfo
SnapshotState. SUCCESS. equals(snapshotInfo. state())). forEach(snapshotInfo->{
list. add(snapshotInfo. snapshotId(). getName());
});
return list;
}
private CloseIndexResponse closeIndices( List< String>indicesList) throws IOException
{
CloseIndexRequest closeIndexRequest = new CloseIndexRequest(indicesList. toArray( new String[indicesList. size()]));
return restHighLevelClient. indices(). close(closeIndexRequest,RequestOptions. DEFAULT);
}
private void deleteByIndicesName( List< String> indicesNameList) throws IOException
{
for ( String indicesName :indicesNameList){
DeleteIndexRequest request= new DeleteIndexRequest();
request. indices(indicesName);
try{
if (elasticSearchService. isIndexExist(indicesName)) {
AcknowledgedResponse deleteResponse =
restHighLevelClient. indices(). delete( request,RequestOptions. DEFAULT);
if (deleteResponse. isAcknowledged()) {
Example example = new Example(IndicesRestore. class);
example. createCriteria(). andEqualTo("restoredIndexName",
indicesName);
IndicesRestore restore= new IndicesRestore();
restore. setDelFlag(1);
indicesRestoreMapper. updateByExampleSelective( restore,
example);
}
}
} catch ( Exception e){
log. error("索引:{}删除失败",indicesName, e);
throw e;
}
}
}
//snapshotDelete 方法用于删除符合特定条件的索引,并更新相关记录。通过创建查询条件、执行查询、提取索引名称列表、调用删除方法和异常处理来完成删除操作。
public void snapshotDelete() throws IOException {
Example example = new Example(IndicesRestore. class);
example. createCriteria(). andEqualTo("delFlag", 0). andLessThan("delTime", new Date());
List
indicesRestoreMapper. selectByExample( example);
List< String>indicesNameList= new ArrayList<>();
for (IndicesRestore restore: restores){
indicesNameList. add( restore. getRestoredIndexName());
}
deleteByIndicesName(indicesNameList);
}
//根据指定条件恢复索引,并在恢复过程中更新相关的数据库记录,确保系统的状态一致性。
public void restoreIndices( Long id) {
Example example = new Example(IndicesRestoreRecord. class);
Example. Criteria criteria= example. createCriteria();
if( id != null&& id!=0){
criteria. andEqualTo("id", id);
}
criteria. andEqualTo("isSuccess", false);
List
indicesRestoreRecordMapper. selectByExample( example);
for (IndicesRestoreRecord restoreRecord: records){
String jsonIndices = restoreRecord. getIndicesName();
List< String> indicesList =JSONArray. parseArray(jsonIndices, String. class);
List< String>notExistsIndicesList= indicesList. stream(). filter( index - >
!elasticSearchService. isIndexExist( index)
). collect( Collectors. toList());
if(!notExistsIndicesList. isEmpty()) {
try{
restoreSnapshot(restoreRecord. getRepositoryName(),
restoreRecord. getSnapshotName(), notExistsIndicesList, restoreRecord. getDelTime(), restoreRecord. getId());
} catch (IOException e){
log. error("索引恢复发生异常,[快照名:{}] [RepositoryName:{}]
[ indices:{}]", restoreRecord. getSnapshotName(), restoreRecord. getRepositoryName(),notExistsIndicesList,e);
}
}
}
}
//主要功能是在 Elasticsearch 中执行搜索查询,并返回匹配的结果。
public PageInfo
Example example = new Example(IndicesRestoreRecord. class);
Example. Criteria criteria= example. createCriteria();
criteria. andLike("indicesName", "%"+ indexName+"%");
if ( type != null){
criteria. andEqualTo("isSuccess", type);
}
PageHelper. startPage(pageIndex, pageSize);
PageInfo
PageInfo<>(indicesRestoreRecordMapper. selectByExample( example));
return pageInfo;
}
}