MST

星途 面试题库

面试题:ElasticSearch 近实时搜索中的缓存机制与性能

ElasticSearch 为实现近实时搜索有多种缓存机制。请详细说明节点查询缓存、过滤器缓存以及字段数据缓存的工作原理,并且分析在近实时搜索场景下,如何合理配置和使用这些缓存来提升性能,以及可能存在的问题和解决方案。
21.6万 热度难度
数据库ElasticSearch

知识考点

AI 面试

面试题答案

一键面试

节点查询缓存(Node Query Cache)

  1. 工作原理:节点查询缓存存储的是整个查询的结果集。当一个查询被执行时,Elasticsearch 首先检查节点查询缓存中是否已经存在该查询的结果。如果存在,则直接返回缓存的结果,而无需再次执行查询。缓存是基于查询的哈希值进行存储和查找的,相同的查询哈希值对应相同的缓存结果。
  2. 合理配置与使用
    • 启用缓存:在 elasticsearch.yml 中设置 indices.queries.cache.enable: true 来启用节点查询缓存。
    • 设置缓存大小:可以通过 indices.queries.cache.size 来设置缓存大小,例如 indices.queries.cache.size: 10%,表示缓存大小占堆内存的 10%。对于读多写少,且查询相对固定的场景,适当增大缓存大小可以显著提升性能。
  3. 可能存在的问题及解决方案
    • 缓存失效不及时:当索引数据发生变化时,缓存中的结果可能不再准确。解决方案是 Elasticsearch 会在索引数据发生更改时,自动使相关的查询缓存失效。但如果更新频繁,缓存失效也频繁,可能影响性能,此时可考虑减少缓存大小或对更新操作进行批量处理。
    • 内存占用:如果缓存设置过大,可能导致 JVM 内存不足。可通过监控 JVM 内存使用情况,动态调整缓存大小。

过滤器缓存(Filter Cache)

  1. 工作原理:过滤器缓存存储的是过滤器查询的结果,即哪些文档满足过滤条件。过滤器通常是无状态的,且具有幂等性,相同的过滤器在相同的数据上总是返回相同的结果。当执行一个带有过滤器的查询时,Elasticsearch 会先检查过滤器缓存中是否有该过滤器的结果。如果有,直接使用缓存结果来快速筛选文档,无需再次计算过滤条件。
  2. 合理配置与使用
    • 默认启用:过滤器缓存默认是启用的。
    • 缓存大小控制:通过 indices.filter.cache.size 来设置,如 indices.filter.cache.size: 20%,表示占堆内存的 20%。对于经常使用过滤器的查询,适当增大该值可以提升性能。例如在基于时间范围、固定枚举值等过滤条件的查询中效果显著。
  3. 可能存在的问题及解决方案
    • 内存压力:如果缓存过多过滤器结果,会占用大量内存。可通过监控内存使用,合理调整缓存大小。对于不常用的过滤器,可以手动使其缓存失效,释放内存。
    • 缓存共享问题:不同分片可能存在相同过滤器的缓存,造成内存浪费。Elasticsearch 在一定程度上会共享相同过滤器的缓存,但对于复杂场景可能效果不佳。此时可考虑对过滤器进行合并或优化,减少不必要的缓存。

字段数据缓存(Field Data Cache)

  1. 工作原理:字段数据缓存用于存储倒排索引中字段的正排数据,以便在排序、聚合等操作中快速访问文档的字段值。当需要对某个字段进行排序或聚合时,如果该字段的字段数据不在缓存中,Elasticsearch 会从磁盘读取倒排索引,构建正排数据并放入缓存。下次再对该字段进行相同操作时,就可以直接从缓存中获取数据。
  2. 合理配置与使用
    • 按需使用:由于构建字段数据缓存可能消耗大量内存和 I/O,应避免对大文本字段等不适合排序或聚合的字段使用字段数据缓存。
    • 缓存预热:在系统启动或负载高峰前,可以通过预先执行一些包含排序或聚合的查询,来填充字段数据缓存,提高后续查询性能。
  3. 可能存在的问题及解决方案
    • 内存消耗大:尤其是对大数据量的字段,构建缓存可能导致内存不足。可以通过设置 indices.fielddata.cache.size 来限制缓存大小,如 indices.fielddata.cache.size: 30%。同时,对于不需要长期保留在缓存中的字段数据,可以设置合理的过期时间。
    • 构建成本高:首次构建字段数据缓存可能需要大量 I/O 和 CPU 资源。可以通过优化索引结构,如使用更紧凑的编码方式,减少构建缓存的成本。