ElasticSearch 7.x使用Java代码导出索引中的文档到本地为JSON文件

 在ElasticSearch中,每建立一个索引,至少需要一个主分片和一个副分片。当索引过多的时候,在不加机器的情况下,是非常影响性能的。那有什么办法可以避免不加机器也能提高性能了。当然有:那就是删除一些基本不可能用到的,且索引下文档数特别少的索引。可删除后,有一天需要回复怎么办了,备份起来是个好办法。即:将ES中的数据备份到本地,然后将其压缩。
 索引导出为JSON文本后,高度结构化。因为JSON是K-V形式的,导致key可以无限重复,这样的数据最适合压缩存储,我导出一个索引大概有1.1G,将其压缩后就只有80MB了。
 如图:JSON中每一组数据都有memberId,这样势必造成空间的浪费,压缩后自然可以回避这个问题。
在这里插入图片描述

压缩实现及其解读:


	/** es请求客户端:每个人的用法不一样,此处需要自己去构建链接 **/
    private RestHighLevelClient client;

 /**
     * @param indexName
     *            索引名称
     * @throws IOException
     *             IO异常
     */
    public void exportindex(String indexName) throws IOException {

        String path = "src/main/resources/indexTemp/";

        File file = new File(path);
        if (!file.exists()) {
            file.mkdirs();
        }

        //构建路径
        path = path + indexName + ".json";

        // 设定滚动时间间隔
        Scroll scroll = new Scroll(TimeValue.timeValueMinutes(2L));

        // 查询全部
        SearchRequest searchRequest = new SearchRequest(indexName);

        searchRequest.scroll(scroll);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        // 每次返回1000条数据
        searchSourceBuilder.size(Constant.NUMBER_1000);

        // 备份索引中字段信息(如果不写,默认备份全部,这里需要备份全部,写的话就是备份数组中的字段)
        // searchSourceBuilder.fetchSource(new String[] { "id", "memberId", "realName" }, new  String[] {});

        // bool查询
        BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();

        searchSourceBuilder.query(boolBuilder);

        searchRequest.source(searchSourceBuilder);

        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);

        // 滚动id
        String scrollId = searchResponse.getScrollId();

        // scrollId使用完之后手动清除,减少内存使用量,当然也可以不清理,es会自动清理的,但是没有手动清理好
        ClearScrollRequest clearScrollRequest = new ClearScrollRequest();

        clearScrollRequest.addScrollId(scrollId);

        // 获取命中数组,一要注意两个getHits()方法,第一个是获取SearchHits对象,第二个是获取SearchHit数组
        SearchHit[] hits = searchResponse.getHits().getHits();

        // 将json格式的数据导出到文件中;异常一行的些
        try (BufferedWriter out = new BufferedWriter(new FileWriter(path, true));) {

            for (SearchHit hit : hits) {

                // 读取为String
                String json = hit.getSourceAsString();

                out.write(json);
                out.write("\r\n");
                out.flush();
            }

            // 搜索完第一个1000条后往下继续执行
            while (Objects.nonNull(hits) && hits.length > 0) {

                SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);

                // 再次设置滚动时间
                scrollRequest.scroll(scroll);

                // 执行滚动查询
                searchResponse = client.scroll(scrollRequest, RequestOptions.DEFAULT);

                // 获取滚动id
                scrollId = searchResponse.getScrollId();

                // 加入清除
                clearScrollRequest.addScrollId(scrollId);

                // 返回命中
                hits = searchResponse.getHits().getHits();

                if (Objects.nonNull(hits) && hits.length > 0) {

                    for (SearchHit hit : hits) {

                        // 读取为String
                        String json = hit.getSourceAsString();
                        out.write(json);
                        out.write("\r\n");
                        out.flush();
                    }
                }
            }

            // 最后执行清除:crollId使用完之后手动清除,减少内存使用量,当然也可以不清理,es会自动清理的,但是没有手动清理好
            ClearScrollResponse clearScrollResponse = client.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);

            LOG.info("备份索引结果为:{}", clearScrollResponse.isSucceeded());
        } catch (Exception e) {
            LOG.error("备份索引【{}】失败", indexName, e);
        }
    }

 执行后,json文本会导出到resources目录下,最后压缩一下,大大的节省空间。压缩方法参考: 导出数据库表为sql文件,并进行压缩.

警示:本文是从是一个开发的角度出发,将ES的数据读取出来,然后写到本地,最后进行压缩。索引所占空间如果只有一两个G的大小,是完全没有问题的,大于两个G就最好直接让运维人员将ES数据从服务器上拉取出来,本文的方法也就不是很实用了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值