ES查询的实时性问题详解

简介: ES查询的实时性问题详解

前言


我们都知道ES是一款近实时的搜索引擎产品。那么为什么是近实时而不是实时呢?为什么新添加的数据开始查询不到,后来又可以检索到?有哪些办法能够提高ES的实时性呢?

今天让我们一起来探究ES查询的实时性问题。


一、实战演示


1、新建索引

在settings中通过refresh_interval参数指定索引每60s刷新一次。

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "city": {
        "type": "keyword"
      }
    }
  },
  "settings": {"refresh_interval": "60s"}
}

2、添加数据


PUT my-index-000001/_doc/1
{
  "city": "北京"
}
PUT my-index-000001/_doc/2
{
  "city": "天津"
}
PUT my-index-000001/_doc/3
{
  "city": "武汉"
}
POST my-index-000001/_doc/4?refresh=true
{ "city": "成都" }



3、GET API

通过索引id查询记录


GET my-index-000001/_doc/1


执行结果:

{
  "_index" : "my-index-000001",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "_seq_no" : 0,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "city" : "北京"
  }
}


说明

新增的数据立刻被检索到,说明GET API是实时的。


GET API主要包含以下请求:

GET <index>/_doc/<_id>
HEAD <index>/_doc/<_id>
GET <index>/_source/<_id>
HEAD <index>/_source/<_id>


默认情况下,Get API 是实时的,不受索引刷新率的影响(当数据对搜索可见时)。 如果请求存储的字段(请参阅 stored_fields 参数)并且文档已更新但尚未刷新,则 get API 将必须解析和分析源以提取存储的字段。 为了禁用实时 GET,可以将 realtime 参数设置为 false。


GET my-index-000001/_doc/1?realtime=false


4、query查询


GET my-index-000001/_search
{
  "query": {
    "bool": {
      "filter": [
        {"term": {
           "city": "北京" 
        }}
      ]
    }
  }
}
## 新增数据并刷新
POST my-index-000001/_doc/4?refresh=true
{ "city": "成都" }
GET my-index-000001/_search
{
  "query": {
    "bool": {
      "filter": [
        {"term": {
           "city": "成都" 
        }}
      ]
    }
  }
}


执行结果:

在新增北京记录操作的60s内执行查询操作,没有查询到新增的记录,因为还没有执行refresh动作。

而新增成都记录时,由于添加了refresh=true参数,会在执行添加操作后立刻执行refresh动作,所以可以根据条件即时查询到成都的记录。


二、ES写入过程分析


83.png


ES写入过程说明:


1.不断将 Document 写入到 In-memory buffer (内存缓冲区)。

2.当满足一定条件后内存缓冲区中的 Documents刷新到 高速缓存(cache)。

3.生成新的 segment ,这个 segment 还在 cache 中。 (在cache中生成的segment就可以被检索到了)

4.这时候还没有 commit,但是已经可以被读取了。

5.translog 事务日志主要用来失败恢复,防止服务器宕机出现内存中没有刷写到磁盘的数据丢失。

数据从 buffer 到 cache 的过程是定期每秒刷新一次。所以新写入的 Document 最慢 1 秒就可以在 cache 中被搜索到。


而 Document 从 buffer 到 cache 的过程叫做 refresh ,默认是 1 秒刷新一次。这也就是为什么说 Elasticsearch 是准实时的。


Elasticsearch通过引入translog,多副本,以及定期执行flush,merge等操作保证了数据可靠性和较高的存储性能。


document同时写入In-memory buffer (内存缓冲区)和translog的过程类似mysql中的double write,主要目的也是失败恢复,防止数据丢失。translog是顺序追加写入。


使文档立即可见:


PUT /test/_doc/1?refresh
{"test": "test"}
// 或者
PUT /test/_doc/2?refresh=true
{"test": "test"}


三、Get API的实时性


简单来说,就是通过get请求直接根据id获取索引记录,是实时操作。

#默认情况下,get API是实时的
GET my-index-000001/_doc/0
#通过realtime=false设置请求为非实时
GET my-index-000001/_doc/0?realtime=false


(注: 如果是realtime=true, 则先从translog中读取source, 没有读取到才从索引中读取)


四、java API中实时性


在ES 的java API中,如何控制数据写入操作后,即时刷新,使得新增的数据立即可见呢?

答案是通过刷新策略WriteRequest.RefreshPolicy。


下面的代码演示,采用highLevelClient.bulk实现批量插入数据中,通过bulkRequest.setRefreshPolicy指定刷新策略为即使刷新。

public boolean bulk(String indice, List<String> jsonStrList) {
        boolean result = true;
        try {
            BulkRequest bulkRequest = new BulkRequest();
            //设置刷新策略
            bulkRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
            for (String jsonStr : jsonStrList) {
                IndexRequest indexRequest = new IndexRequest(indice,"_doc");
                indexRequest.source(jsonStr, XContentType.JSON);
                bulkRequest.add(indexRequest);
            }
            BulkResponse bulkResponse = highLevelClient.bulk(bulkRequest);
            if (bulkResponse.hasFailures()) {
                result = false;
            }
        } catch (Exception e) {
            result = false;
        }
        return result;
    }


查看源码发现:


public static enum RefreshPolicy implements Writeable {
        NONE("false"),
        IMMEDIATE("true"),
        WAIT_UNTIL("wait_for");
          ……
}


可知有以下三种刷新策略:


1.RefreshPolicy#IMMEDIATE:

请求向ElasticSearch提交了数据,立即进行数据刷新,然后再结束请求。

优点:实时性高、操作延时短。

缺点:资源消耗高。

2.RefreshPolicy#WAIT_UNTIL:

请求向ElasticSearch提交了数据,等待数据完成刷新,然后再结束请求。

优点:实时性高、操作延时长。

缺点:资源消耗低。

3.RefreshPolicy#NONE:

默认策略。

请求向ElasticSearch提交了数据,不关系数据是否已经完成刷新,直接结束请求。

优点:操作延时短、资源消耗低。

缺点:实时性低。


总结


文本主要对ES数据写入后查询的实时性问题进行了分析。

1、通过分析ES的写入流程,说明了ES查询数据为什么会产生延迟,即为什么说ES是准实时的

2、说明了Get API默认是实时的原因,主要是Get API默认情况下优先读取的是translog中的数据。

3、可以通过设置refresh_interval参数,缩短索引refresh的间隔时间,增大实时性。

4、可以通过写入操作后添加refresh参数,让写入的数据被即时检索到。

5、介绍了ES java API中通过设置写入操作的刷新策略RefreshPolicy,改变写入数据的实时性。

相关实践学习
以电商场景为例搭建AI语义搜索应用
本实验旨在通过阿里云Elasticsearch结合阿里云搜索开发工作台AI模型服务,构建一个高效、精准的语义搜索系统,模拟电商场景,深入理解AI搜索技术原理并掌握其实现过程。
ElasticSearch 最新快速入门教程
本课程由千锋教育提供。全文搜索的需求非常大。而开源的解决办法Elasricsearch(Elastic)就是一个非常好的工具。目前是全文搜索引擎的首选。本系列教程由浅入深讲解了在CentOS7系统下如何搭建ElasticSearch,如何使用Kibana实现各种方式的搜索并详细分析了搜索的原理,最后讲解了在Java应用中如何集成ElasticSearch并实现搜索。 &nbsp;
目录
相关文章
|
canal
阿里云DTS同步binlog实战
阿里云DTS同步binlog实战
1760 0
|
应用服务中间件 索引 nginx
生产环境ES查询延迟排查
最近经常收到业务方配置的ES查询延迟告警,同样的请求手动在Kibana控制台执行只需几十毫秒就返回结果。受影响的整个链路情况如下,php应用程序通过部署在ES集群各节点上的nginx访问ES请求查询数据。
6088 0
|
Java Spring
Spring Boot 排除自动配置的 4 种方法,关键时刻很有用!
Spring Boot 提供的自动配置非常强大,某些情况下,自动配置的功能可能不符合我们的需求,需要我们自定义配置,这个时候就需要排除/禁用 Spring Boot 某些类的自动化配置了。
Spring Boot 排除自动配置的 4 种方法,关键时刻很有用!
|
存储 缓存 自然语言处理
Elasticsearch 查询性能优化:从 3 秒到 300ms 的 6 个核心参数调优指南
本文分享某电商平台 Elasticsearch 性能调优实战,通过调整分片数、刷新间隔、缓存配置等 6 个核心参数,将商品搜索从 3 秒优化至 300 毫秒,显著提升查询性能与系统吞吐量。内容涵盖性能诊断、参数调优逻辑、实操方案及避坑指南,助力高频查询场景下的 ES 优化。
|
前端开发 Java Spring
SpringBoot2.6.x 整合swagger3.0 报错Failed to start bean ‘documentationPluginsBootstrapper‘
org.springframework.context.ApplicationContextException: Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException
16894 3
SpringBoot2.6.x 整合swagger3.0 报错Failed to start bean ‘documentationPluginsBootstrapper‘
|
12月前
|
消息中间件 监控 Kubernetes
别再乱排查了!Kafka 消息积压、重复、丢失,根源基本都是 Rebalance!
大家好,我是小富~分享一次Kafka消息积压排查经历:消费者组因Rebalance导致消费能力骤降。本文详解Rebalance触发场景(消费者变更、分区扩容、订阅变化、超时等),剖析其引发的消息积压、重复消费、丢失等问题根源,并提供优化方案:调优超时参数、手动提交offset、启用粘性分配策略、保障消费幂等性。掌握这些,轻松应对Kafka常见故障!
2066 0
|
人工智能 Java Scala
Springboot捕获feign抛出的异常
本文探讨了在使用Springboot与Feign客户端时,如何有效捕获接口异常的问题。由于全局异常无法直接捕获Feign抛出的异常,文章提供了具体解决方案:通过定义自定义异常类`BusinessException`,结合`ErrorDecoder`对Feign请求异常进行处理,或在全局异常捕获中添加特定处理器。示例代码详细展示了配置与实现步骤,帮助开发者更好地应对Feign客户端的异常处理需求。
612 2
|
存储 Java 关系型数据库
【Elasticsearch 技术分享】—— 十张图带大家看懂 ES 原理 !明白为什么说:ES 是准实时的!
说到 Elasticsearch ,其中最明显的一个特点就是 near real-time 准实时 —— 当文档存储在Elasticsearch中时,将在1秒内以几乎实时的方式对其进行索引和完全搜索。那为什么说 ES 是准实时的呢?
1936 0
|
存储 分布式计算 网络协议
【Elasticsearch】elasticsearch.yml配置文件解读,ES配置详解
【Elasticsearch】elasticsearch.yml配置文件解读,ES配置详解
2472 0
|
监控 安全 Java
ElasticSearch在Windows上的下载与安装
ElasticSearch在Windows上的下载与安装