一、问题描述
针对ElasticSearch进行搜索,两次完全一致的搜索语句(在两次搜索过程中,没有更新、删除、新增等操作),第一次和第二次的返回结果不一致,之后的搜索结果又没有变化。
这种异常不是很常见,不容易复现,之前遇到过,没放在心上,于是上官网查了查。
二、个人总结
1.首先,可能是ES近实时的特性的影响,因为更新、新增等操作并不是实时的(详见:ElasticSearch 基本原理(四)近实时(Near Real Time ,NRT)分析);
2.集群有问题,不稳定(例如集群是黄色,只有主分片可用,部分副本不可用),两次搜索结果在不同的分片、副本进行,且分片、副本数据并没有完全一致;
三、官网解决方案
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-preference.html
搜索的时候指定分片,默认情况下是随机的,以下是指定分片的preference搜索的属性:
_primary: 指查询只在主分片中查询
_primary_first: 指查询会先在主分片中查询,如果主分片找不到(挂了),就会在副本中查询。
_local: 指查询操作会优先在本地节点有的分片中查询,没有的话再在其它节点查询。
_only_node:指在指定id的节点里面进行查询,如果该节点只有要查询索引的部分分片,就只在这部分分片中查找,所以查询结果可能不完整。如_only_node:123在节点id为123的节点中查询。
_prefer_node:nodeid 优先在指定的节点上执行查询
Custom (string) value:用户自定义值,指在参数cluster.routing.allocation.awareness.attributes指定的值,如这个值设置为了zone,那么preference=zone的话就在awareness.attributes=zone*这样的节点搜索,如zone1、zone2。
7 _shards:0,1,2,3,4:查询指定分片的数据
指定分片缺点:非常明显,这会影响性能,正常情况下分片和副本的数据是保持一致的,指定分片搜索必要性不大。至于是否使用,这需要根据业务指定。
四、代码
SearchRequestBuilder requestBuilder = client.prepareSearch("test")
.setTypes("test")
.setPreference("_primary_first")
.setQuery(boolQueryBuilder)
.setFrom(1)
.setSize(5);
参考: 分片查询方式