如果您在针对_id主键或开启fielddata的text类型字段做排序、聚合查询、脚本查询等操作时,遇到搜索结果返回慢、页面加载延迟等体验问题,可以优先根据本文查看fielddata内存使用情况,如果fielddata内存使用率较高,可以参考本文定位并解决该问题。
背景信息
大量Elasticsearch(ES)集群运维案例显示,fielddata内存使用率越小越好,fielddata不需要占用明显的堆内存。但在Elasticsearch(ES)运维场景中,经常会遇到fielddata内存使用率高,严重时导致整个集群不可用的监控场景。
问题场景
fieldata缓存主要包含field data和global ordinals,占用fielddata的业务场景主要包含:
前两个场景占用fielddata缓存较多,且影响较大,请优先关注。
针对
_id
主键做排序、agg查询和脚本查询操作。解决方案:
Elasticsearch官方文档中指出禁止对
_id
进行聚合、排序和脚本操作,建议将_id
数据复制到开启doc_values
的字段进行对应操作。Kibana Discover通过
_id
查询数据时,下拉提示功能会自动触发聚合。建议在Kibana > StackManagement > 高级设置中关闭
filterEditor:suggestValues
,避免在Kibana中根据主键进行搜索时,执行大量_id
字段的聚合分析。
对开启fielddata的text类型字段进行聚合、排序和脚本查询操作。
解决方案:
text字段默认关闭fielddata,开启后可进行聚合、排序和脚本查询操作。如果加载高基数text字段,fielddata会占用大量的堆内存,并且堆内存占用是永久的,建议将字段类型改成keyword。
keyword和ip等类型的字段,进行terms aggregations和composite aggregations等查询。
join字段的parent和child文档aggregations。
问题排查
您可以通过高级监控报警、fielddata API和热线程三种方式,查看fileddata内存使用率是否过高。
高级监控报警
阿里云Elasticsearch高级监控报警服务在社区版监控的基础上扩展了更细粒度的监控,尤其对集群运维提供了非常大的帮助。
- 登录阿里云Elasticsearch控制台。
在左侧导航栏,单击高级监控报警。
在高级监控报警页面,选择 。
在默认基础指标页签中,查看fielddata内存使用指标。
fielddata API
- 登录目标阿里云Elasticsearch实例的Kibana控制台,根据页面提示进入Kibana主页。登录Kibana控制台的具体操作,请参见登录Kibana控制台。说明 本文以阿里云Elasticsearch 7.10.0版本为例,其他版本操作可能略有差别,请以实际界面为准。
- 单击右上角的Dev tools。
在Console页签中,执行以下命令,查看各个节点的fielddata内存占用情况(fielddata.memory_size)。
GET _cat/nodes?v&h=ip,heap.percent,heap.current,heap.max,ram.current,ram.percent,fielddata.memory_size
预期结果如下。
热线程
通过线程分析当前集群正在处理哪类耗时任务,以便聚焦根因定位。
GET _nodes/hot_threads
通过以下结果可以看到,热线程正在处理fielddata.ordinals.GlobalOrdinalsBuilder,即在构建全局序数。
问题分析
您可以通过fielddata API和日志两种方式,分析导致fielddata内存占用高问题的原因。
fielddata API
执行以下命令,获取占用fielddata内存占用高的字段,分析和业务的哪类查询相关。
GET _cat/fielddata?v&s=size:desc
预期结果如下。
日志聚焦查询
通过在阿里云Elasticsearch控制台中分析实例慢日志,查看是否存在导致fielddata内存占用高问题的操作,详细信息请参见查询日志。例如以下日志中存在查询时按照_id排序的操作,导致fielddata内存占用高。
解决方案
您可以通过以下方案,临时解决fielddata内存占用高的问题:
通过_cache/clear指定fielddata,清理fielddata缓存。如果不指定,将清理所有缓存。
POST _cache/clear?fielddata=true
重要通过API清理缓存是一种临时方案,请结合业务环境评估后操作。该操作会加长查询耗时,消耗额外的计算资源,可能会加重集群服务压力。
建议您从业务具体查询角度进行优化,否则即使进行了清理操作,后续查询压力仍可能回升至较高水平。例如,_id的查询场景,建议您新建一个字段,把数据写入新字段,通过新字段做查询。
强制重启集群。
具体操作请参见重启实例或节点。
说明因fielddata内存占用高,导致fielddata占用大量的堆内存且集群不可访问时,建议优先选择强制重启集群,恢复集群可访问状态。