• 内存吞金兽(Elasticsearch)的那些事儿 -- 常见问题痛点及解决方案


    系列目录

    内存吞金兽(Elasticsearch)的那些事儿 -- 认识一下

    内存吞金兽(Elasticsearch)的那些事儿 -- 数据结构及巧妙算法

    内存吞金兽(Elasticsearch)的那些事儿 -- 架构&三高保证

    内存吞金兽(Elasticsearch)的那些事儿 -- 写入&检索原理

    内存吞金兽(Elasticsearch)的那些事儿 -- 常见问题痛点及解决方案

    1、大数据量的查询效率如何保证:

    查询的流程:往 ES 里写的数据,实际上都写到磁盘文件里去了,查询的时候,操作系统会将磁盘文件里的数据自动缓存到 Filesystem Cache 里面去

    最佳的情况下,就是机器的内存,至少可以容纳总数据量的一半,仅仅在 es 中就存少量的数据,就是要用来搜索的那些索引,如果内存留给 filesystem cache 的是 100G,那么将索引数据控制在 100G 以内,这样的话,数据几乎全部走内存来搜索,性能非常之高,一般可以在 1 秒以内,但是生成环境的数据量往往还是会很多,有大致四种方案:

    1)数据预热

    平时看的人很多的数据,每隔一会儿,去搜索一下热数据,刷到 filesystem cache 里去,后面用户实际上来看这个热数据的时候,就是直接从内存里搜索了;

    2)冷热分离

    将大量的访问很少、频率很低的数据,单独写一个索引,然后将访问很频繁的热数据单独写一个索引。最好是将冷数据写入一个索引中,然后热数据写入另外一个索引中,这样可以确保热数据在被预热之后,尽量都让他们留在 filesystem os cache 里,别让冷数据给冲刷掉。

    3)es+Hbase架构: 

    es只存储索引字段,其他数据放到mysql/hbase中;

    举例说明:id,name,age .... 30 个字段。现在搜索,只需要根据 id,name,age 三个字段来搜索。如果往 es 里写入一行数据所有的字段,就会导致说 90% 的数据是不用来搜索的,结果硬是占据了 es 机器上的 filesystem cache 的空间,单条数据的数据量越大,就会导致 filesystem cahce 能缓存的数据就越少。其实,仅仅写入 es 中要用来检索的少数几个字段就可以了,比如说就写入es id,name,age 三个字段,然后你可以把其他的字段数据存在 mysql/hbase 里,我们一般是建议用 es + hbase 这么一个架构。

    4)document 模型设计
    对于 MySQL,我们经常有一些复杂的关联查询。es 里面的复杂的关联查询尽量别用,一旦用了性能一般都不太好。

    要先在 Java 系统里就完成关联,将关联好的数据直接写入 es 中。搜索的时候,就不需要利用 es 的搜索语法来完成 join 之类的关联搜索了。

    2、分页查询痛点及解决方案:

    假设现在要查询第100页的10条数据,但是对于es来说,from=1000000,size=100,这时 es需要从各个分片上查询出来10000100条数据,然后汇总计算后从其中取出100条。如果有5个分片则需要查询出来5*10000100条数据,如果现在有并发的100个查询请求,就会有50亿左右的数据,占用的内存是非常高的,所以在使用es的分页查询过程中,刚开始翻页可能速度比较快,可能到第一百页查询就需要4-5s,翻到1000页以后,系统资源占用成指数级上升,很容易就会出现OOM直接报错。

    分页方案:

    1)基本的from-size查询,es为了避免深度分页带来的内存开销,from最大值设定到了10000,目前后台运营的翻页最多关心近10页的数据;

    2)search after按照第一个检索到的最后显示的“balance”和‘_id’值,作为下一个检索search_after的参数,例如假定size是10,当查询990-1000时,通过上次传递的最后一个检索到的值,在分片上就可以取到10条文档,不支持上一页查询。

    3)scroll查询

    scroll查询原理是在第一次查询的时候一次性生成一个快照,根据上一次的查询的id来进行下一次的查询,这个就类似于关系型数据库的游标,然后每次滑动都是根据产生的游标id进行下一次查询,这种性能比上面说的分页性能要高出很多,基本都是毫秒级的。

    注意点:scroll不支持跳页查询。

    使用场景:对实时性要求不高的查询。

    代码:

    设置查询条件

    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
           QueryBuilder builder = QueryBuilders.queryStringQuery("123456").field("code");
           boolQueryBuilder.must(QueryBuilders.termQuery("logType""10"))
                   .must(builder);

    首次查询

    • 第一次查询,跟平时的search查询一样需要设置index和type以及查询条件。
    • 如果把查询类型设置成SCAN,那么不能获取结果并且不支持排序,只能获得scrollId,如果使用默认设置或者不设置,那么第一次在获取id的同时也可以获取到查询结果。
    • 这个size大小的意思不是总分页的大小,实际数量应该是:所以实际返回的数量是:分片的数量*size
    • 滚动时间设置是指在这个查询搜索结果的缓存时间,时间不能太久,毕竟内存空间是有限的。
    SearchResponse response1 = client.prepareSearch("_audit_0221").setTypes("_log_0221")
                        .setQuery(boolQueryBuilder)
                        .setSearchType(.setSearchType(SearchType.DEFAULT))
                        .setSize(10).setScroll(TimeValue.timeValueMinutes(5))
                        .addSort("logTime"SortOrder.DESC)
                        .execute().actionGet();//第一次查询
    for (SearchHit searchHit : response1.getHits().hits()) {
                biz handle....;
    }

    第二次查询

                for (SearchHit searchHit : response1.getHits().hits()) {
                }
                        .execute().actionGet();
            }

    4) 利用scroll-scan遍历数据

    使用场景:500w用户,需要遍历所有用户发送数据,并且对顺序没有要求,这个时候我们可以使用scroll-scan。

    查询
     SearchResponse response = client.prepareSearch("_audit_0221").setTypes("_log_0221")
                        .setQuery(boolQueryBuilder)
                        .setSearchType(SearchType.SCAN)
                        .setSize(5).setScroll(TimeValue.timeValueMinutes(5))
                        .addSort("logTime"SortOrder.DESC)
                        .execute().actionGet();
    获取结果
                    .execute().actionGet();
     
                for (SearchHit searchHit : response1.getHits().hits()) {
                }
                        .execute().actionGet();
    }


    scroll和scroll-scan区别

    1. scroll支持排序,scroll-scan不支持排序,是按照索引顺序返回,可以提高查询效率。

    2. scroll-scan第一次查询只支持返回id,没有结果。

    总结:

      1. es的分页查询不支持深度分页,如果偏要使用要结合具体业务场景进行使用。不能当成关系型数据库中的分页进行使用。
      2. 要想提高产品体验和查询效率不能过于依赖技术,要结合需求进行分析以提高体验,因为很多搜索类产品都不支持深度分页。
      3. 如果在不涉及排序的情况下尽量使用scroll-scan,它是按照索引顺序返回,提高效率。
    (C) 房上的猫 。 保留所有权利。 https://www.cnblogs.com/lsy131479/ 如需转载,请注明出处!!!
  • 相关阅读:
    iOS中Zbar二维码扫描的使用
    SOJ 1135. 飞跃原野
    SOJ 1048.Inverso
    SOJ 1219. 新红黑树
    SOJ 1171. The Game of Efil
    SOJ 1180. Pasting Strings
    1215. 脱离地牢
    1317. Sudoku
    SOJ 1119. Factstone Benchmark
    soj 1099. Packing Passengers
  • 原文地址:https://www.cnblogs.com/lsy131479/p/15184427.html
Copyright © 2020-2023  润新知