ElasticSearch 8.x 使用 snapshot(快照)进行数据迁移

news2024/11/17 0:40:54

ElasticSearch

1、ElasticSearch学习随笔之基础介绍
2、ElasticSearch学习随笔之简单操作
3、ElasticSearch学习随笔之java api 操作
4、ElasticSearch学习随笔之SpringBoot Starter 操作
5、ElasticSearch学习随笔之嵌套操作
6、ElasticSearch学习随笔之分词算法
7、ElasticSearch学习随笔之高级检索
8、ELK技术栈介绍
9、Logstash部署与使用
10、ElasticSearch 7.x 版本使用 BulkProcessor 实现批量添加数据
11、ElasticSearch 8.x 弃用了 High Level REST Client,移除了 Java Transport Client,推荐使用 Elasticsearch Java API
12、ElasticSearch 8.x 使用 snapshot(快照)进行数据迁移
13、ElasticSearch 8.x 版本如何使用 SearchRequestBuilder 检索

ElasticSearch,创始人 Shay Banon(谢巴农)
本文主要讲解ElasticSearch 数据快速迁移。


文章目录

  • ElasticSearch
  • 前言
  • 一、什么是ES的快照
  • 二、快照生成
    • 2.1 新建仓库
      • 2.1.1 Kibana操作
      • 2.1.2 JAVA API操作
        • 2.1.2.1 引入 pom 依赖
        • 2.1.2.2 初始化客户端
        • 2.1.2.3 创建仓库(参数方式)
        • 2.1.2.3 创建仓库(配置文件方式)
    • 2.2 生成快照
      • 2.2.1 Kibana操作
      • 2.2.2 JAVA API操作
    • 2.3 删除快照
      • 2.3.1 Kibana操作
      • 2.3.2 JAVA API操作
  • 三、恢复快照
    • 3.1 Kibana操作
    • 3.2 JAVA API操作


前言

平时在工作中,很多时候都是需要搭建好几个测试平台来保证应用的运行是否流畅,有没有 Bug,数据是否正确,一般都是 dev、pre 等测试环境,通过一系列的测试之后没有什么问题,才会把 应用 和 数据 部署到 prod 环境,应用一般都是大包 prod 环境的部署包,直接部署,而数据则就需要很长的实际来同步了,如果是一些统计咨询类的企业应用,那数据上线就有可能花费掉大量的时间了。
此篇就来浅谈一下,项目中应用到了 ElasticSearch 来做数据检索,那在项目上线的时候,我们如何快速的把大量数据快速从一个 ElasticSearch索引迁移到另一个索引库。
快照和恢复
A snapshot is a backup of a running Elasticsearch cluster.
官网上说,一个快照就是一个备份在 Elasticsearch 集群上运行的时候,快照可以用于以下几点:

  • 集群服务不停的情况下定期备份数据;
  • 删除或者硬件出错后恢复数据;
  • 在两台集群中间传输数据;
  • 通过在冷和冻结数据层中使用可搜索的快照来降低存储成本;

那具体什么是快照呢?

一、什么是ES的快照

Elasticsearch 的快照就是指对数据和元数据的定期备份。因为快照中不仅包含了所有数据,也包含了所有的相关信息,比如:映射、配置等;这些快照可以保存在本地文件系统,也可以保存在共享文件系统或者专门存储快照的地方。

在快照的概念中,数据并不都是每次全部备份一遍,而是采用增量的方式进行进行备份。首次备份会进行全力备份,而后续的备份则是在上一次备份后的更新的数据,增量备份可以有效地减少备份所需的存储空间和节省时间。

对于 Elasticsearch 的迁移,快照和恢复则是很常用的一种强大的方式,在源集群上创建索引的快照,拷贝到其他集群后在恢复,也可以用 API 的方式来进行快照和恢复,这里就用 JAVA + Elasticsearch Client 实现,这样在我们后台应用就可以完成数据迁移了。

二、快照生成

2.1 新建仓库

2.1.1 Kibana操作

可以通过 Kibana 指令来注册快照,命令如下:

POST _snapshot/productInfo
{
  "type": "fs",
  "settings": {
    "location": "/data/esbackup/product_info"
  }
}

执行以上指令,有可能报错,一般会报如下错误:

"caused_by": {
  "type": "repository_exception",
  "reason": "[productInfo] location [/data/esbackup] doesn't match any of the locations specified by path.repo because this setting is empty"
}

报上述错误一般是 Elasticsearch 服务没有配置 path.repo 这个参数,只需要在 elasticsearch.yml 中配置 path.repo: /data/repository 即可。

如果报错如下:

"caused_by": {
  "type": "access_denied_exception",
  "reason": "/data/repository/tests-gU8mf7EvREG_1qMc3ZMApQ"
}

说明你配置的 path.repo 的路径没有访问权限,赋予权限即可:
chown -R elasticsearch:elasticsearch /data/esbackup/productInfo/

2.1.2 JAVA API操作

2.1.2.1 引入 pom 依赖
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>7.3.2</version>
</dependency>

注意: 再次感受到 elasticsearch-rest-high-level-client 对版本的严格区分,可能是我的 ElasticSearch 配置或者是其他原因,低版本的客户端使用 BulkProcessor 是没有问题的,但是在 获取快照 操作测报错,高版本的客户端在 获取快照时没问题,但是在 BulkProcessor 批量操作数据时报错,你的是否也有这个问题呢?

2.1.2.2 初始化客户端
/**
 * 通过认证连接ES,获取客户端
 */
public static RestHighLevelClient createClient(){
    String hostname = "192.168.*.*";
    int port = 9200;
    String username = "your username";
    String password = "your password";
    final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
    credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
    RestClientBuilder restClientBuilder = RestClient.builder(new HttpHost(hostname, port))
            .setHttpClientConfigCallback(httpAsyncClientBuilder -> httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider));
    return new RestHighLevelClient(restClientBuilder);
}
2.1.2.3 创建仓库(参数方式)
/**
 * 创建仓库
 */
public static void createRepository(RestHighLevelClient client, String repositoryName) {
    GetRepositoriesRequest getRepositoriesRequest = new GetRepositoriesRequest(new String[]{repositoryName});
    boolean hasRepository = false;
    try {
        GetRepositoriesResponse repository = client.snapshot().getRepository(getRepositoriesRequest, RequestOptions.DEFAULT);
        List<RepositoryMetadata> repositories = repository.repositories();
        for (RepositoryMetadata repositoryMetadata : repositories) {
            if(repositoryMetadata.name().equals(repositoryName)){
                hasRepository = true;
                break;
            }
        }
    } catch (ElasticsearchStatusException ee) {
        System.out.println("仓库不存在:" + ee.getMessage());
    } catch (IOException ioException) {
        // 客户端版本略低,所以用异常捕获方式判断,索引存在会抛到这里异常
        System.err.println(ioException.getMessage());
        hasRepository = true;
    }
    if(!hasRepository){
        try {
            PutRepositoryRequest repositoryRequest = new PutRepositoryRequest();
            repositoryRequest.name(repositoryName);
            repositoryRequest.verify(false);
            repositoryRequest.name(repositoryName);
            repositoryRequest.type("fs");
            repositoryRequest.settings(Settings.builder().put("location", "/data/esbackup/productInfo"));
            AcknowledgedResponse acknowledgedResponse = client.snapshot().createRepository(repositoryRequest, RequestOptions.DEFAULT);
            if (acknowledgedResponse.isAcknowledged()) {
                System.out.println("创建仓库成功: " + repositoryName);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    try {
        client.close();
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}
2.1.2.3 创建仓库(配置文件方式)
  • 配置文件如下:
    src/main/resources/productInfo.json
{
  "type": "fs",
  "settings": {
    "location": "/data/esbackup/productInfo",
    "compress": true
  }
}
  • 读取配置,创建仓库:
    注意:仓库名称 repositoryName 必须小写
/**
 * 创建仓库
 */
public static void createRepository(RestHighLevelClient client, String settingPath, String repositoryName) {
    GetRepositoriesRequest getRepositoriesRequest = new GetRepositoriesRequest(new String[]{repositoryName});
    boolean hasRepository = false;
    try {
        GetRepositoriesResponse repository = client.snapshot().getRepository(getRepositoriesRequest, RequestOptions.DEFAULT);
        List<RepositoryMetadata> repositories = repository.repositories();
        for (RepositoryMetadata repositoryMetadata : repositories) {
            if(repositoryMetadata.name().equals(repositoryName)){
                hasRepository = true;
                break;
            }
        }
    } catch (ElasticsearchStatusException ee) {
        System.out.println("仓库不存在:" + ee.getMessage());
    } catch (IOException ioException) {
        // 客户端版本略低,所以用异常捕获方式判断,索引存在会抛到这里异常
        System.err.println(ioException.getMessage());
        hasRepository = true;
    }
    if(!hasRepository){
        try {
            String jsonString = new String(Files.readAllBytes(Paths.get(settingPath)), StandardCharsets.UTF_8);
            // 解析 json
            PutRepositoryRequest repositoryRequest = new PutRepositoryRequest();
            XContentParser contentParser = XContentFactory.xContent(XContentType.JSON).createParser(NamedXContentRegistry.EMPTY, DeprecationHandler.THROW_UNSUPPORTED_OPERATION, jsonString);
            repositoryRequest.name(repositoryName);
            repositoryRequest.verify(false);
            repositoryRequest.source(contentParser.map());
            AcknowledgedResponse acknowledgedResponse = client.snapshot().createRepository(repositoryRequest, RequestOptions.DEFAULT);
            if (acknowledgedResponse.isAcknowledged()) {
                System.out.println("创建仓库成功: " + repositoryName);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    try {
        client.close();
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

2.2 生成快照

2.2.1 Kibana操作

POST _snapshot/product_info/product_info

2.2.2 JAVA API操作

注: 快照名称 snapshotName 必须小写

/**
 * 生成快照
 */
public static boolean createSnapshot(RestHighLevelClient client, String snapshotName, String repositoryName, String... indexes) {
    CreateSnapshotRequest createSnapshotRequest = new CreateSnapshotRequest();
    createSnapshotRequest.indices(indexes);
    createSnapshotRequest.snapshot(snapshotName);
    createSnapshotRequest.repository(repositoryName);
    createSnapshotRequest.waitForCompletion(true);
    createSnapshotRequest.includeGlobalState(false);
    try {
        CreateSnapshotResponse snapshotResponse = client.snapshot().create(createSnapshotRequest, RequestOptions.DEFAULT);
        SnapshotInfo snapshotInfo = snapshotResponse.getSnapshotInfo();
        if (snapshotInfo.status().getStatus() == 200) {
            System.out.println("快照创建成功:" + snapshotInfo);
            return true;
        }
    } catch (IOException e){
        e.printStackTrace();
    } finally {
        try {
            client.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    return false;
}

快照生成成功,如图:
快照

2.3 删除快照

2.3.1 Kibana操作

DELETE _snapshot/product_info

2.3.2 JAVA API操作

/**
 * 删除快照
 */
public static boolean deleteSnapshot(RestHighLevelClient client, String repositoryName) {
    DeleteSnapshotRequest deleteSnapshotRequest = new DeleteSnapshotRequest();
    deleteSnapshotRequest.snapshots(repositoryName);
    deleteSnapshotRequest.repository(repositoryName);
    try {
        AcknowledgedResponse deleteSnapshotResponse = client.snapshot().delete(deleteSnapshotRequest, RequestOptions.DEFAULT);
        if (deleteSnapshotResponse.isAcknowledged()) {
            System.out.println("快照删除成功!");
            return true;
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            client.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    return false;
}

三、恢复快照

3.1 Kibana操作

POST _snapshot/product_info/product_info/_restore
{
  "indices": "product_info"
}

3.2 JAVA API操作

/**
     * 恢复快照
     */
    public static void restoreSnapshot(RestHighLevelClient client, String snapshotName, String repositoryName, String indexes){
        RestoreSnapshotRequest restoreSnapshotRequest = new RestoreSnapshotRequest();
        restoreSnapshotRequest.snapshot(snapshotName);
        restoreSnapshotRequest.repository(repositoryName);
        restoreSnapshotRequest.indices(indexes);
        try {
            RestoreSnapshotResponse restoreSnapshotResponse = client.snapshot().restore(restoreSnapshotRequest, RequestOptions.DEFAULT);
            System.out.println("快照恢复成功:" + restoreSnapshotResponse.getRestoreInfo().toString());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                client.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1419921.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于Java SSM框架实现影院购票系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现影院购票系统演示 摘要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&#…

MySQL进阶45讲【8】MySQL事务到底是隔离的还是不隔离的?

1 前言 在 MySQL进阶45讲【3】事务隔离的恩恩怨怨 这篇文章和大家讲事务隔离级别的时候提到过&#xff0c;如果是可重复读隔离级别&#xff0c;事务T启动的时候会创建一个视图read-view&#xff0c;之后事务T执行期间&#xff0c;即使有其他事务修改了数据&#xff0c;事务T看…

can中继方案

为了实现灵活的网络拓扑&#xff0c;不受主干线和直线的长度限制以及终端电阻的位置限制。产生了can中继的需求。 安森美的AMIS-42600-D芯片可以实现can总线扩展、CAN总线中继等需求。AMIS-42700 A

吉利汽车:S-SDLC融入开发体系,推动智能汽车安全发展

吉利汽车是中国汽车行业的知名品牌&#xff0c;是一家具有国际化视野的汽车企业&#xff0c;在中国汽车市场自主品牌中占据领军地位。吉利汽车集团数字化中心利用数字化技术优势赋能业务升级&#xff0c;推动研发效率提升和产品安全能力拓展&#xff0c;进行整体数字化转型。 在…

PyTorch2ONNX-分类模型:速度比较(固定维度、动态维度)、精度比较

图像分类模型部署: PyTorch -> ONNX 1. 模型部署介绍 1.1 人工智能开发部署全流程 #mermaid-svg-bAJun9u4XeSykIbg {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-bAJun9u4XeSykIbg .error-icon{fill:#552222;}…

5G安卓核心板开发板_MT6833天玑700规格参数

核心板采用沉金生产工艺&#xff0c;耐腐蚀抗干扰&#xff0c;支持-20℃-70℃环境下7x24小时稳定运行&#xff0c;尺寸仅为45mmx48mm x2.65mm&#xff0c;可嵌入到各种智能产品中&#xff0c;助力智能产品便携化及功能差异化。 联发科MT6833处理器采用台积电 7nm 制程的5G SoC…

基于YOLOv8深度学习的水稻叶片病害智能诊断系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

USB-C显示器:未来显示技术的革新者

随着科技的不断发展&#xff0c;显示技术也在不断进步&#xff0c;而USB-C显示器作为最新的显示技术&#xff0c;正在引领着显示行业的发展潮流。USB-C显示器具有许多优点&#xff0c;如高速传输、便捷连接、节能环保等&#xff0c;使其成为未来显示技术的革新者。 一、USB-C显…

[Grafana]ES数据源Alert告警发送

简单的记录一下使用es作为数据源&#xff0c;如何在发送告警是带上相关字段 目录 前言 一、邮件配置 二、配置 1.Query 2.Alerts 总结 前言 ES作为数据源&#xff0c;算是Grafana中比较常见的&#xff0c;Alerts告警是我近期刚接触&#xff0c;有一个需求是当表空间大于…

Apache SeaTunnel (不含web) Window11 本机搭建(非源码)

启动环境 需要提前准备的(只提供作者试过且可行的方案) window11ubuntu20(wsl2) window11内置ubuntu的方式自行百度&#xff0c;此处不做陈述jdk8mysql8navicatvscode 环境准备不做过多陈述&#xff0c;以下是正式的安装启动步骤 SeaTunnel 2.3.3 资源准备 第一步: 创建文件…

基于Javaweb开发的二手图书零售系统详细设计【附源码】

基于Javaweb开发的二手图书零售系统详细设计【附源码】 &#x1f345; 作者主页 央顺技术团队 &#x1f345; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; &#x1f345; 文末获取源码联系方式 &#x1f4dd; &#x1f345; 查看下方微信号获取联系方式 承接各种定制系统…

【webrtc】‘ninja.exe‘ 不是内部或外部命令,也不是可运行的程序及vs2019 重新构建m98

werbtc 就是用ninja.exe 来构建找到了自己以前构建的webrtc 原版 m98 【m98 】webrtc ninja 构建 、example、tests 及OWT- P2P 项目P2PMFC-E2E-m98G:\CDN\rtcCli\webrtc-checkout\src找到了自己的deptools的路径 deptools里确实没有ninja.exe D:\SOFT\depot_tools\third_party…

Nginx进阶篇【五】

Nginx进阶篇【五】 八、Nginx实现服务器端集群搭建8.1.Nginx与Tomcat部署8.1.1.环境准备(Tomcat)8.1.1.1.浏览器访问:8.1.1.2.获取动态资源的链接地址:8.1.1.3.在Centos上准备一个Tomcat作为后台web服务器8.1.1.4.准备一个web项目&#xff0c;将其打包为war8.1.1.5.启动tomcat进…

数据结构奇妙旅程之七大排序

꒰˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN …

欧拉计划第816题:求大量点的最短距离

本次来解决欧拉计划的第816题: 解: 第一步:最原始的算法 先从简单的情况开始,即原题里的14个点的情况 import mathdef gen_points(n):s = [0] * (2*n)s[0] = 290797for i in range(1, 2*n):s[i] = (s[i - 1] * s[i - 1]) % 50515093p = [(s[2 * i], s[2 * i + 1]) for…

Android悬浮窗的实现

最近想做一个悬浮窗秒表的功能&#xff0c;所以看下悬浮窗具体的实现步骤 1、初识WindowManager 实现悬浮窗主要用到的是WindowManager SystemService(Context.WINDOW_SERVICE) public interface WindowManager extends ViewManager {... }WindowManager是接口类&#xff0c…

【HTML教程】跟着菜鸟学语言—HTML5个人笔记经验(五)完结

HTML学习第五天 PS&#xff1a;牛牛只是每天花了1.5-2小时左右来学习HTML。这也是最后一天&#xff0c;其实HTML只需要1-2天就可以学完&#xff01; 书接上回 HTML 脚本 JavaScript 使 HTML 页面具有更强的动态和交互性。 尝试一下&#x1f3f7; 插入一段脚本 <!DOCT…

C语言菜鸟入门·判断语句(if语句、if...else语句、嵌套if语句)详细介绍

目录 1. if语句 2. if...else语句 3. if...else if...else 语句 4. 嵌套if语句 C 语言把任何非零和非空的值假定为 true&#xff0c;把零或 null 假定为 false。 语句描述if语句一个 if 语句 由一个布尔表达式后跟一个或多个语句组成。if...else语句一个 if 语句 后可跟…

Flutter 应用服务:主题、暗黑、国际化、本地化-app_service库

Flutter应用服务 主题、暗黑、国际化、本地化-app_service库 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/article/det…

FullStack之Django(1)开发环境配置

FullStack之Django(1)开发环境配置 author: Once Day date&#xff1a;2022年2月11日/2024年1月27日 漫漫长路&#xff0c;才刚刚开始… 全系列文档请查看专栏: FullStack开发_Once_day的博客-CSDN博客Django开发_Once_day的博客-CSDN博客 具体参考文档: The web framewor…