Elasticsearch:cache 在 Elasticsearch 中的应用

本文探讨了Elasticsearch中的缓存机制,包括Pagecache、Shard-Level Request Cache和Query Cache,介绍了它们如何提高查询性能,以及在调整分片数量时对缓存和性能的影响。此外,文章提供了使用filter进行查询优化的示例,展示了如何利用缓存提升查询效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

缓存在提高查询性能方面发挥了重要作用,不同类型的缓存用于存储经常访问的数据,这有助于加快搜索查询速度并减轻集群的负载。 这些类型的缓存用于优化查询性能并减少集群上的负载。 每个缓存都有特定的用途,了解它们的工作原理可以帮你微调搜索查询以获得更好的性能。

Page cache 是如何工作的

在 Elasticsearch 的使用中,有如下的几种 cace:

  1. Page cache:该缓存是由操作系统维护的缓存。 它用于在内存中存储经常访问的数据。 发生的事情是 Elasticsearch 利用页面缓存通过缓存频繁访问的数据来加速搜索查询 —— 当进行搜索时,Elasticsearch 首先检查页面缓存以查看所需的数据是否已在内存中可用,如果是,Elasticsearch 将尝试检索它来自页面缓存,这比从磁盘读取它快得多。
  2. Shard-Level Request Cache:该类型用于缓存在集群中的每个分片上执行的搜索请求的结果,默认情况下启用。 你可以将其配置为存储多个请求或在一个时间窗口内发出的请求。 这个缓存的信息在所有节点之间共享,它存储了每个分片上执行的最近请求的结果。 当一个新的请求被执行时,Elasticsearch 会检查缓存,看看最近是否在同一个分片上执行过相同的请求,如果找到,那么它会尝试从缓存中检索结果,而不是再次执行查询,这将有助于提高查询性能。
  3. Query Cache:该缓存用于维护和存储所有频繁执行的查询的结果 —— 当我们谈论查询缓存时,这里是执行查询时发生的事情。 我可以告诉你为什么我们这样做有性能优势,Elasticsearch 检查这个查询是否在某个时间窗口之前执行过,如果找到这个查询,Elasticsearch 将尝试从缓存中检索所有结果而不是再次执行查询,这缓存配置为根据一组参数存储查询,例如查询类型和结果集的大小,你甚至可以配置为根据使用的搜索过滤器进行缓存。

专业提示:有时,增加 Elasticsearch 集群中的分片数量很有趣,但是,当你增加 Elasticsearch 中的分片数量时,你实际上是将数据分成更小的块,并将其分布在集群中的多个节点上。 这会对性能和缓存产生积极和消极的影响。

从积极的方面来说,拥有更多分片可以提高搜索性能,因为可以跨多个节点并行执行查询。 它还可以提高集群的整体可扩展性,因为你可以添加更多节点来处理增加的工作负载。

但是,拥有更多分片也会增加集群的开销,因为每个分片都需要自己的资源,例如内存和磁盘空间。 这可能导致更高的资源利用率和可能更慢的查询响应时间。 在缓存方面,拥有更多分片会使有效缓存数据变得更加困难。 这是因为缓存在每个分片的基础上运行,所以如果你有大量分片,你可能需要为缓存分配更多内存才能达到相同的性能水平。

此外,当你拥有更多分片时,你可能会遇到更多的缓存逐出,即从缓存中删除较旧或访问频率较低的数据以为新数据腾出空间。 这可能会导致较低的缓存命中率,从而对查询性能产生负面影响 —— 增加 Elasticsearch 中的分片数量会对性能和缓存产生积极和消极的影响。 在决定使用多少分片时,请务必仔细考虑您的要求和用例,并相应地监控和优化您的集群以实现最佳性能。

在所有的应用中,cache 是个好东西。因为是在内存里,它的访问速度快,而且有时甚至直接进行使用,这样它就无形加快我们的搜索速度。默认情况下 cache 是启动的。你也可以通过如下的方式来关掉 cache:

PUT /my-index-000001
{
  "settings": {
    "index.requests.cache.enable": false
  }
}

在今天的文章中,我将分享几个小的技巧。希望对大家的学习有所帮助。为了方便我们的讲解,我们先使用 Kibana 自带的索引来进行展示。

准备数据

在今天的教程中,我们将使用 Kibana 自带的索引来进行展示。打开 Kibana 界面:

点击 Add data:

这样我们的样本数据就导入进 Elasticsearch 了。通过上面的操作,我们在 Elasticsearch 中将生成一个叫做 kibana_sample_data_logs 的索引。

使用 filter 还是一般的查询?

在 Elasticsearch 中,如果使用 filter 的话,它将被 cache,从而可以帮我们提高性能。在使用 filter 时,必须注意的一点就是 filter 不会对我们的最终的分数有任何的影响,也就是说,如果你不想这个部分的查询对分数有所影响,你首先 filter,而且尽量使用 filter。

我们先对我们的 kibana_sample_data_logs 来进行操作:

GET kibana_sample_data_logs/_search
{
  "query": {
    "range": {
      "@timestamp": {
        "gte": "2020-07-26",
        "lte": "2020-08-03"
      }
    }
  }
}

上面的查询结果是:

  "hits" : {
    "total" : {
      "value" : 2096,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "kibana_sample_data_logs",
        "_type" : "_doc",
        "_id" : "Rm84uHMBZS6OOEix1ZMc",
        "_score" : 1.0,
        "_source" : {
          "agent" : "Mozilla/5.0 (X11; Linux x86_64; rv:6.0a1) Gecko/20110421 Firefox/6.0a1",
          "bytes" : 6219,
          "clientip" : "223.87.60.27",
          "extension" : "deb",
          "geo" : {
            "srcdest" : "IN:US",
            "src" : "IN",
            "dest" : "US",
            "coordinates" : {
              "lat" : 39.41042861,
              "lon" : -88.8454325
            }
          },
          "host" : "artifacts.elastic.co",
          "index" : "kibana_sample_data_logs",
          "ip" : "223.87.60.27",
          "machine" : {
            "ram" : 8589934592,
            "os" : "win 8"
          },
          "memory" : null,
          "message" : "223.87.60.27 - - [2018-07-22T00:39:02.912Z] \"GET /elasticsearch/elasticsearch-6.3.2.deb_1 HTTP/1.1\" 200 6219 \"-\" \"Mozilla/5.0 (X11; Linux x86_64; rv:6.0a1) Gecko/20110421 Firefox/6.0a1\"",
          "phpmemory" : null,
          "referer" : "http://twitter.com/success/wendy-lawrence",
          "request" : "/elasticsearch/elasticsearch-6.3.2.deb",
          "response" : 200,
          "tags" : [
            "success",
            "info"
          ],
          "timestamp" : "2020-07-26T00:39:02.912Z",
          "url" : "https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.3.2.deb_1",
          "utc_time" : "2020-07-26T00:39:02.912Z",
          "event" : {
            "dataset" : "sample_web_logs"
          }
        }
      },
    ...

在上面的查询中,它是不被 cache 的,同时我们可以看到分数(_score)都为 1.0。

如果这个查询我们经常会用,并且我们不关心搜索结果的分数,那么,我们可以使用 filter 来代替上面的 range 查询:

GET kibana_sample_data_logs/_search
{
  "query": {
    "bool": {
      "filter": [
        {
          "range": {
            "@timestamp": {
              "gte": "2020-07-26",
              "lte": "2020-08-03"
            }
          }
        }
      ]
    }
  }
}

上面的返回结果的结果是:

  "hits" : {
    "total" : {
      "value" : 2096,
      "relation" : "eq"
    },
    "max_score" : 0.0,
    "hits" : [
      {
        "_index" : "kibana_sample_data_logs",
        "_type" : "_doc",
        "_id" : "Rm84uHMBZS6OOEix1ZMc",
        "_score" : 0.0,
        "_source" : {
          "agent" : "Mozilla/5.0 (X11; Linux x86_64; rv:6.0a1) Gecko/20110421 Firefox/6.0a1",
          "bytes" : 6219,
          "clientip" : "223.87.60.27",
          "extension" : "deb",
          "geo" : {
            "srcdest" : "IN:US",
            "src" : "IN",
            "dest" : "US",
            "coordinates" : {
              "lat" : 39.41042861,
              "lon" : -88.8454325
            }
          },
          "host" : "artifacts.elastic.co",
          "index" : "kibana_sample_data_logs",
          "ip" : "223.87.60.27",
          "machine" : {
            "ram" : 8589934592,
            "os" : "win 8"
          },
          "memory" : null,
          "message" : "223.87.60.27 - - [2018-07-22T00:39:02.912Z] \"GET /elasticsearch/elasticsearch-6.3.2.deb_1 HTTP/1.1\" 200 6219 \"-\" \"Mozilla/5.0 (X11; Linux x86_64; rv:6.0a1) Gecko/20110421 Firefox/6.0a1\"",
          "phpmemory" : null,
          "referer" : "http://twitter.com/success/wendy-lawrence",
          "request" : "/elasticsearch/elasticsearch-6.3.2.deb",
          "response" : 200,
          "tags" : [
            "success",
            "info"
          ],
          "timestamp" : "2020-07-26T00:39:02.912Z",
          "url" : "https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.3.2.deb_1",
          "utc_time" : "2020-07-26T00:39:02.912Z",
          "event" : {
            "dataset" : "sample_web_logs"
          }
        }
      },

上面的分数(_score)显示为0,也就是说它不计入分数。使用这种 filter 的方式,查询是使用 cache,也就是说,当你第二次或之后使用同样的查询,你的速度将会大大提高,这是因为查询的结果来自cache。由于我们的数据有限,所以,我们看不出来时间的差异。对于大量的数据来说,我们可以看到第二次及之后的同一个查询的速度将会大大提高。

另外的一个例子就是:

GET kibana_sample_data_logs/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "geo.src": "CN"
          }
        },
        {
          "range": {
            "@timestamp": {
              "gte": "2020-07-26",
              "lte": "2020-08-03"
            }
          }
        }
      ]
    }
  }
}

在这里,我们查来自 CN 的,并且在 2020-07-26 和 2020-08-03 之间的所有文档。我们最好修改为:

GET  kibana_sample_data_logs/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "geo.src": "CN"
          }
        }
      ],
      "filter": [
        {
          "range": {
            "@timestamp": {
              "gte": "2020-07-26",
              "lte": "2020-08-03"
            }
          }
        }
      ]
    }
  }
}

当然在任何的情况下,我们可以使用 request_cache=true 来强制使用 cache:

GET kibana_sample_data_logs/_search?request_cache=true
{
  "query": {
    "range": {
      "@timestamp": {
        "gte": "2020-07-26",
        "lte": "2020-08-03"
      }
    }
  }
}

在 aggregation 时设置 size=0 会自动 cache

即使在索引设置中启用了请求缓存,也不会缓存 size大于0的请求。如果你想使用缓存,一种办法就是把 size 置为 0。

我们打入如下的命令:

GET kibana_sample_data_logs/_search
{
  "size": 0,
  "aggs": {
    "src_countries": {
      "terms": {
        "field": "geo.src",
        "size": 10
      }
    }
  }
}

我们可以运行上面的命令多次,在返回的时间里:

我们会发现,第二次执行的时间比第一次的要少。如果我们去掉 size:0,那么:

GET kibana_sample_data_logs/_search
{
  "aggs": {
    "src_countries": {
      "terms": {
        "field": "geo.src",
        "size": 10
      }
    }
  }
}

那么这个搜索是不会缓存的。对于小的数据集来说,这个可能并不明显,但是对于大的数据集的查询来说,你将会看到很大的变化。

如果你确实不想把 size 设置为0, 那么,你必须在请求的时候,明显地指出来:

GET kibana_sample_data_logs/_search?request_cache=true
{
  "aggs": {
    "src_countries": {
      "terms": {
        "field": "geo.src",
        "size": 10
      }
    }
  }
}

最后强调的一点就是当 Lucene 的 segements 在 merge 的时候,这些 cache 将会变成无效。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值