ES中结果震荡问题分析

CASE:

场景:

查询时出现“同一个DSL语句执行多次结果不一致”,如查询时返回的结果时而出现total=16,时而出现18...

 

配置

refresh_interval = -1; 3节点;2 primary 1 replica;

 

分析

主要的原因是因为有副本(replica)的存在,主分片和副本分片可能不一致,导致最终在主分片和副本分片上计算得到的得分不同,而导致最终的查询结果不一致。

不同的查询请求落到不同的分片上,获取到的文档集就可能不一致,最终才会出现hits.total一会是18,一会为16这种情况。

但是是如何造成主分片和副本分片不一致的情况?

1.可能是因为用户删除了部分文档,之后主分片进行了merge, 而副本分片没有进行merge。 这种情况下主分片和副本分片上的总文档数量就会不同,打分时计算出的IDF的值不同,最终得到了不同的得分。

2.当文档被删除或更新时,旧文档不会立即从索引中删除,它只是标记为已删除,并且仅在下次合并该旧文档所属的segment时才从磁盘中删除; 假设主分片刚刚完成了一个大型merge,删除了许多已删除的文档,那么它的索引统计信息可能与副本(仍具有大量已删除文档)完全不同(副本分片不会和主分片一起进行merge操作),因此得分也有所不同。

3.如果两个文档相关性评分相同,会根据其内部Lucene文档ID对其进行排序,两个文档相同的主分分片,luceneID不一定相同,导致最后的结果不一定相同

官方文档类似问题解释:https://www.elastic.co/guide/en/elasticsearch/reference/6.4/consistent-scoring.html

 

解决方案:

preference参数可以用来指定分片查询的优先级,可以通过该参数来控制搜索时的索引数据分片。

不设置该参数:在所有有效的主分片以及副本间轮询

可以用来处理结果震荡问题: 搜索同一query,结果ES返回的顺序却不尽相同,这就是请求轮询到不同分片,而未设置排序条件,相同相关性评分情况下,是按照所在segment中​lucene id来排序的,相同数据的不同备份之间该id是不能保证一致的,故造成结果震荡问题。

如设置该参数,则有一下9种情况:

`_primary`:发送到集群的相关操作请求只会在主分片上执行。

`_primary_first`:指查询会先在主分片中查询,如果主分片找不到(挂了),就会在副本中查询。

`_replica`:发送到集群的相关操作请求只会在副本上执行。

`_replica_first`:指查询会先在副本中查询,如果副本找不到(挂了),就会在主分片中查询。

`_local`: 指查询操作会优先在本地节点有的分片中查询,没有的话再在其它节点查询。

`_prefer_nodes:abc,xyz`:在提供的节点上优先执行(在这种情况下为'abc'或'xyz')

`_shards:2,3`:限制操作到指定的分片。 (`2`和“3”)。这个偏好可以与其他偏好组合,但必须首先出现:`_shards:2,3 | _primary`

`_only_nodes:node1,node2`: 指在指定id的节点里面进行查询,如果该节点只有要查询索引的部分分片,就只在这部分分片中查找,不同节点之间用“,”分隔。

 

custom(自定义):注意自定义的preference参数不能以下划线"_"开头。 当preference为自定义时,即该参数不为空,且开头不以“下划线”开头时。

特别注意:如果以用户query作为自定义preference时,一定要处理以下划线开头的情况,这种情况下如果不属于以上8种情况,则会抛出异常。

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值