ElasticSearch调优篇 11 - 搜索结果震荡问题解决+排查命令
1、震荡问题
搜索同一 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种情况,则会抛出异常。
我们在实际情况中解决此类问题一般会采用两种方案:
- 使用 preference = '_primary_first' 参数来进行搜索,这样优先使用主节点进行搜索,当主节点挂掉后会打到副本进行搜索。
- 缺点:会给 主节点 造成很大的压力,因为 index 也会先索引主节点后通过批量打包的方式快速同步,而 search 又都集中在主节点,会造成主节点 cpu 升高,内存增加。
- 使用 preference = custom 参数来进行搜索,这样在 preference 后拼接一个用户 uid 或 openudid,这样就能保证每个人使用相同的搜索词重复搜索最终展现的结果是一致的。
2、排查命令
1、热点线程,即最耗 cpu 或 内存 对应的线程,且起对应执行的线程栈
GET /_nodes/hot_threads
2、指定某节点的热点线程
GET _nodes/MFW10.133.1.30-9202/hot_threads
3、查看当前 es 集群所有节点线程池状况
GET /_cat/thread_pool?pretty
4、查看当前 es 集群所有节点指定类型线程池状况以及格式化详情,例如:search 类型
GET /_cat/thread_pool/search?v&h=ip,port,type,name,active,rejected,completed,size,queue,queue_size
5、查看当前 es 集群所有节点指定类型线程池状况以及格式化详情,例如:index 类型
GET /_cat/thread_pool/index?v&h=ip,port,type,name,active,rejected,completed,size,queue,queue_size