AWS ElasticSearch同match_phrase_prefix查询不同节点返回异常
异常根因
这个问题核心是3号分片的主/副本数据或索引状态不一致,两个节点上存的3号分片副本(包含主分片)的倒排索引内容有差异,才会出现同查询不同节点返回结果不一样的情况。
对应你观察到的现象逻辑很明确:
- 查询词和目标字段完全一致时,走的是精确term匹配,两个副本上都存了对应完整分词的term条目,所以都能正常返回结果
- 用
match_phrase_prefix做前缀匹配时,需要扫描本地倒排索引里所有以0700为前缀的term,如果其中一个副本的倒排索引里缺了07001这个term和文档的关联关系,或者前缀扫描依赖的FST字典、segment状态异常,自然就扫不到对应文档。
常见触发原因有这几种:
- 之前分片副本同步的时候碰到过网络闪断、节点OOM重启,部分segment没同步完成,集群也没自动触发副本修复
- AWS ES做滚动升级的时候两个节点版本暂时没对齐,不同版本的分词逻辑、前缀查询执行逻辑有细微差异
- 之前对索引做过强制合并、段升级操作,过程中节点异常退出,导致主副本的segment组成不一致
- 短时间的refresh差异也可能导致这个问题,但这种情况一般几分钟内就会自动恢复,不会长期存在
排查与修复步骤
按顺序操作即可:
- 先确认分片副本的基础状态
执行下面的命令查看3号分片的主副本角色、同步状态、文档数、存储大小差异:
对比两个节点上3号分片的GET _cat/shards/carat-prod?v&h=index,shard,prirep,state,docs,store,node,iddocs和store字段值,如果数值不一样,直接就能确定是副本数据不一致。 - 校验两个节点的分词结果一致性
分别指定路由到两个节点执行分词测试,确认相同文本的分词输出完全一致:
把请求里的节点ID换成POST _only_nodes:xQVLroD1RoCShwwzLwXY4g/carat-prod/_analyze { "field": "content", "text": "10 Blahblahblah Avenue Apt. 42 Banana, NJ 07001" }gn9dYu4pS22gNEDeCg6RrQ再执行一次,对比两次返回的term列表,如果有差异,说明两个节点的ES版本、自定义分词插件版本没对齐,先统一版本再查问题。 - 修复异常副本
如果确认是副本同步异常导致的数据不一致,直接调用reroute接口把返回空结果的节点上的3号分片标记为陈旧副本,触发集群从正常分片重新同步数据:
如果返回空结果的节点上存的是主分片,就把命令里的node值换成能正常返回结果的节点ID,操作前确认索引至少有1个健康副本,不会出现数据丢失。POST _cluster/reroute { "commands": [ { "allocate_stale_primary": { "index": "carat-prod", "shard": 3, "node": "xQVLroD1RoCShwwzLwXY4g", "accept_data_loss": false } } ] } - 长期规避
给索引设置index.translog.durability: request,适当调大副本同步的超时时间,避免大分片同步时中途中断产生不一致副本;AWS托管ES可以开启自动分片校验功能,定期扫描主副本的数据差异自动修复。
内容的提问来源于stack exchange,提问作者Sergey Voronkov
相关产品推荐
相关产品推荐

