面试题答案
一键面试节点查询缓存(Node Query Cache)
- 工作原理:节点查询缓存存储的是整个查询的结果集。当一个查询被执行时,Elasticsearch 首先检查节点查询缓存中是否已经存在该查询的结果。如果存在,则直接返回缓存的结果,而无需再次执行查询。缓存是基于查询的哈希值进行存储和查找的,相同的查询哈希值对应相同的缓存结果。
- 合理配置与使用:
- 启用缓存:在
elasticsearch.yml
中设置indices.queries.cache.enable: true
来启用节点查询缓存。 - 设置缓存大小:可以通过
indices.queries.cache.size
来设置缓存大小,例如indices.queries.cache.size: 10%
,表示缓存大小占堆内存的 10%。对于读多写少,且查询相对固定的场景,适当增大缓存大小可以显著提升性能。
- 启用缓存:在
- 可能存在的问题及解决方案:
- 缓存失效不及时:当索引数据发生变化时,缓存中的结果可能不再准确。解决方案是 Elasticsearch 会在索引数据发生更改时,自动使相关的查询缓存失效。但如果更新频繁,缓存失效也频繁,可能影响性能,此时可考虑减少缓存大小或对更新操作进行批量处理。
- 内存占用:如果缓存设置过大,可能导致 JVM 内存不足。可通过监控 JVM 内存使用情况,动态调整缓存大小。
过滤器缓存(Filter Cache)
- 工作原理:过滤器缓存存储的是过滤器查询的结果,即哪些文档满足过滤条件。过滤器通常是无状态的,且具有幂等性,相同的过滤器在相同的数据上总是返回相同的结果。当执行一个带有过滤器的查询时,Elasticsearch 会先检查过滤器缓存中是否有该过滤器的结果。如果有,直接使用缓存结果来快速筛选文档,无需再次计算过滤条件。
- 合理配置与使用:
- 默认启用:过滤器缓存默认是启用的。
- 缓存大小控制:通过
indices.filter.cache.size
来设置,如indices.filter.cache.size: 20%
,表示占堆内存的 20%。对于经常使用过滤器的查询,适当增大该值可以提升性能。例如在基于时间范围、固定枚举值等过滤条件的查询中效果显著。
- 可能存在的问题及解决方案:
- 内存压力:如果缓存过多过滤器结果,会占用大量内存。可通过监控内存使用,合理调整缓存大小。对于不常用的过滤器,可以手动使其缓存失效,释放内存。
- 缓存共享问题:不同分片可能存在相同过滤器的缓存,造成内存浪费。Elasticsearch 在一定程度上会共享相同过滤器的缓存,但对于复杂场景可能效果不佳。此时可考虑对过滤器进行合并或优化,减少不必要的缓存。
字段数据缓存(Field Data Cache)
- 工作原理:字段数据缓存用于存储倒排索引中字段的正排数据,以便在排序、聚合等操作中快速访问文档的字段值。当需要对某个字段进行排序或聚合时,如果该字段的字段数据不在缓存中,Elasticsearch 会从磁盘读取倒排索引,构建正排数据并放入缓存。下次再对该字段进行相同操作时,就可以直接从缓存中获取数据。
- 合理配置与使用:
- 按需使用:由于构建字段数据缓存可能消耗大量内存和 I/O,应避免对大文本字段等不适合排序或聚合的字段使用字段数据缓存。
- 缓存预热:在系统启动或负载高峰前,可以通过预先执行一些包含排序或聚合的查询,来填充字段数据缓存,提高后续查询性能。
- 可能存在的问题及解决方案:
- 内存消耗大:尤其是对大数据量的字段,构建缓存可能导致内存不足。可以通过设置
indices.fielddata.cache.size
来限制缓存大小,如indices.fielddata.cache.size: 30%
。同时,对于不需要长期保留在缓存中的字段数据,可以设置合理的过期时间。 - 构建成本高:首次构建字段数据缓存可能需要大量 I/O 和 CPU 资源。可以通过优化索引结构,如使用更紧凑的编码方式,减少构建缓存的成本。
- 内存消耗大:尤其是对大数据量的字段,构建缓存可能导致内存不足。可以通过设置