ES 多次查询结果不一致,有哪些可能?

背景

ES的搜索应用场景非常丰富,在极端情况下可能会出现同语句多次查询结果不一致的情况,特别是全文检索有打分的场景下。

一般ES如果碰到同一个语句多次查询结果不一致的情况(数量不一致/顺序不一致),一般是如下几种case:

1. DR集群数据不一致

2. 主副分片数据存储的差异(导致打分差异)

    - segment

    - deleted文件(merge独立)

    - 可查询文档(refresh独立)

    - lucene文件id

其中主副分片数据存储的差异(导致打分差异)的case也就是经典的结果震荡问题;

ES集群DR(多数据中心/多集群容灾)主要有3种方式:

- 自研跨数据中心同步方案

- 官方 CCR,收费

- 用户双写

DR集群数据不一致,肯定会对查询造成一定影响,这里不展开讨论。

结果震荡问题

场景

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

分析

1. 主要原因

主分片和副本分片可能不一致,导致最终在主分片和副本分片上计算得到的得分不同,即最终的查询结果不一致。

2. 造成主分片和副本分片不一致的原因

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

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

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

官方文档类似问题解释:

https://www.elastic.co/guide/en/elasticsearch/reference/6.4/consistent-scoring.html

3. 解决方案

a. 指定分片查询(查询偏好:preference)

   - 不指定分片:在所有有效的主分片以及副本间轮询

# ES6版本https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-request-preference.html`_primary`:发送到集群的相关操作请求只会在主分片上执行。`_primary_first`:查询会先在主分片中查询,如果主分片找不到(挂了),就会在副本中查询。`_replica`:发送到集群的相关操作请求只会在副本分片上执行。`_replica_first`:查询会先在副本中查询,如果副本找不到(挂了),就会在主分片中查询。
# ES7版本https://www.elastic.co/guide/en/elasticsearch/reference/7.17/search-search.html#search-preference`_local`:如果可能,请在本地节点上的分片上运行搜索。如果没有,请使用默认方法选择分片。

这里可以看到,ES7不再支持preference直接选择“_primary”。

b. 通过权重的方式增大分数差异

- 极端情况下才会出现结果震荡问题,一般情况下主副本之间带来的打分差异比较小。

- 通过权重调整,可以从业务层解决排序问题。根据权重调整打分的方式有很多种,比如function_score,这里不展开描述。

其他可能

当业务查询非常慢(响应大于1s)并且查询端设置了超时时间的时候,可能由于超时导致查询的数据不完整,多次查询极有可能数据不一致。

GET index_test/_search
{
    "timeout": "1s",
    "query": {
      "match_all": {}
    }
}

此时如果出现查询超时,结果返回将不完整,只返回固定时间内查询到的结果以及total(未查询完成的部分直接忽略),并且带有一个`timed_out=true`的标记,这也是非常容易忽视的一点。

{
  "took": 183,
  "timed_out": true,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 0,
    "max_score": null,
    "hits": []
  }
}

解决方案

1. 降低响应延迟

- 提升 CPU、MEM 配置 / 磁盘使用 SSD

- mapping 优化,ES7之后字段类型的type会较大影响查询性能

- 查询语句优化

查询语句优化的定制化要求比较高:

比如我们遇到的是大量数据(亿级文档数)聚合比较慢,优化主要通过:

- 不使用序数 "execution_hint": "map"- 在查询之前提前创建好全局序数 "eager_global_ordinals": true

2. 增加超时时间

GET index_test/_search
{
    "timeout": "5s",
    "query": {
      "match_all": {}
    }
}

  • 14
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
sqltoy-orm是比hibernate+myBatis更加贴合项目的orm框架,具有hibernate增删改的便捷性同时也具有比myBatis更加灵活优雅的自定义sql查询功能。 sqltoy-orm支持以下数据库: oracle 从oracle11g到19c db2 9.5+,建议从10.5 开始 mysql 支持5.6、5.7、8.0 版本 postgresql 支持9.5 以及以上版本 sqlserver 支持2008到2019版本,建议使用2012或以上版本 sqlite sybase_iq 支持15.4以上版本,建议使用16版本 elasticsearch 只支持查询,版本支持5.7+版本,建议使用7.3以上版本 clickhouse mongodb (只支持查询) sqltoy-orm特性: 1、根本上杜绝了sql注入问题,sql支持写注释、sql文件动态更新检测,开发时sql变更会自动重载。 2、最直观的sql编写模式,当查询条件稍微复杂一点的时候就会体现价值,后期变更维护的时候尤为凸显。 3、极为强大的缓存翻译查询:巧妙的结合缓存减少查询语句表关联,极大简化sql和提升性能。 4、最强大的分页查询:很多人第一次了解到何为快速分页、分页优化这种极为巧妙的处理,还有在count语句上的极度优化。 5、跨数据库函数方言替换,如:isnull/ifnull/nvl、substr/substring 等不同数据库。 sqltoy-orm特点: 1、最优雅直观的sql编写模式 2、天然防止sql注入,执行过程 3、最强大的分页查询 4、最巧妙的缓存应用,将多表关联查询尽量变成单表 5、跨数据库 6、提供行列转换(数据旋转),避免写复杂的sql或存储过程,用算法来化解对sql的高要求,同时实现数据库无关(不管是mysql还是sqlserver) 7、提供分组汇总求平均算法(用算法代替sql避免跨数据库语法不一致) 8、分库分表 9、五种非数据库相关主键生成策略 10、elastic原生查询支持 11、elasticsearch-sql 插件模式sql模式支持     sqltoy-orm框架系统 更新日志: v4.18.22 1、在findEntity中EntityQuery可以设置fetchSize 2、在sqltoyContext中可以全局设置fetchSize,例如 spring.sqltoy.fetchSize=200 3、convertType 支持空集合返回空集合 4、针对一些特殊原因导致表名是数据库关键词的处理支持
ES 文件浏览器是一款多功能的手机文件/程序/进程管理器,可以在手机、电脑、远程和蓝牙间浏览管理文件。是一个功能强大的免费的本地和网络文件管理器和应用程序管理器。适用2.0以上Android机型。ES文件浏览器是一个能管理安卓设备本地、局域网共享、远程FTP、蓝牙设备和云存储的系统工具类移动软件。全球主动下载超过2亿次,安卓文件管理第一品牌。 ES 文件浏览器 ES File Explorer 中文版ES 文件浏览器 ES File Explorer 中文版 想更好地管理你的手机、平板、家里电脑和云端网盘?原生中文支持,全球上亿用户一致选择的最强安卓文件管理器! 点击就可以播放音乐,点击就可以播放视频,点击就可以查看图片,点击就可以阅读文档,点击就可以安装应用,点击就可以查看压缩,点击就可以进行搜索,点击就可以更改视图,还有海量的网盘空间可以存放数据ES 文件浏览器(ES File Explorer)主要功能: *快捷的工具栏操作 *管理手机及局域网计算机上的文件 *在本地和网络中搜索和查看文件 *安装/卸载/备份程序 *压缩/解压 *多选/缩略图/多种视图 *播放网络上的音乐、电影 *蓝牙 【基本信息】 作者:北京亿思创世信息技术有限公司 更新时间:2021-04-12 版本:4.2.4.5 系统:Android 2.2.x以上 语言:中文 ES 文件浏览器 软件特点 类似Windows的平易UI,多视图和排序,简单易用:点击安装程序即可安装,点击文档即可打开,点击媒体文件即可播放。 同时功能强大,高度可定制,多选、搜索、剪贴板的功能提供给资深用户使用; 网络和本地的统一的操作和UI,简单的复制和粘帖代替了文件上传、下载等专业概念; 丰富的系统管理功能,包括内存、进程、SD卡、计算机、手机系统的短信、通讯录、安全等; 文件管理功能:多种视图列表和排序方式,查看并打开各类文件,在本地SD卡、局域网、互联网的计算机之间任意传输文件。多选、复制、粘帖、剪贴板、查看属性、解压、重命名等文件功能; 程序管理功能:安装、卸载、备份程序、创建快捷方式等; 进程管理功能:查看、杀掉系统中运行的进程,有自动记忆等功能; 多媒体功能:内置文本编辑器,可查看文本;可使用系统内置的播放器查看音频视频;软件内置远程媒体播放器来远程播放计算机上的流媒体和其他视频音频文件,软件内置远程图片浏览器来远程浏览图片; FTP功能:可以通过3g、wifi、gprs等方式来访问远程的FTP服务器,远程查看图片、视频等多媒体文件; 局域网文件访问功能:可以通过wifi来访问局域网内的所有计算机,远程查看图片、视频等多媒体文件; 安全管理:加密、备份、短信远程控制等;
实验一 两个多位十进制数相加的实验 一、实验目的 学习数据传送和算术运算指令的用法 熟悉在PC机上建立、汇编、链接、调试和运行汇编语言程序的过 程。 二、实验内容 将两个多位十进制数相加,要求被加数和加数均以ASCII码形式各自 顺序存放在以DATA1、DATA2为首的5个内存单元中(低位在前),结果 送回DATA1处。 三、程序框图 图 3-1 四、参考程序清单 DATA SEGMENT DATA1 DB 33H,39H,31H,37H,34H;被加数 DATA1END EQU $-1 DATA2 DB 34H,35H,30H,38H,32H;加数 DATA2END EQU $-1 SUM DB 5 DUP(?) DATA ENDS STACK SEGMENT STA DB 20 DUP(?) TOP EQU LENGTH STA STACK ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA,SS:STACK,ES:DATA START: MOV AX,DATA MOV DS,AX MOV AX,STACK MOV SS,AX MOV AX,TOP MOV SP,AX MOV SI,OFFSET DATA1END MOV DI,OFFSET DATA2END CALL ADDA MOV AX,4C00H INT 21H ADDA PROC NEAR MOV DX,SI MOV BP,DI MOV BX,05H AD1: SUB BYTE PTR [SI],30H SUB BYTE PTR [DI],30H DEC SI DEC DI DEC BX JNZ AD1 MOV SI,DX MOV DI,BP MOV CX,05H CLC AD2: MOV AL,[SI] MOV BL,[DI] ADC AL,BL AAA MOV [SI],AL DEC SI DEC DI LOOP AD2 MOV SI,DX MOV DI,BP MOV BX,05H AD3: ADD BYTE PTR [SI],30H ADD BYTE PTR [DI],30H DEC SI DEC DI DEC BX JNZ AD3 RET ADDA ENDP CODE ENDS END START 五、实验结果如图: 六、心得体会:这次实验初步接触到上机操作。首先第一次编 程中可能会出现很多的错误,慢慢的认真检查与修改,这次实验熟 练了操作流程,而且这次实验的结果为:两个数相加后结果放在内 存中DS:0000处,且结果应给为84256,实验结果与理论分析一致。 实验二 排序实验 一、实验目的 掌握用汇编语言编写排序程序的思路和方法。 二、实验内容 将指定内存出开始的数据(最多为4位数)按从大到小的顺序排 列。第一个数字表示数据的个数(不是要比较的数值!!!)。 三、程序流程图 图 3-2 四、程序清单 DATA SEGMENT ADDR DW 8,234,35,67,876,54,39,765,237 DATA ENDS STACK SEGMENT STA DW 32 DUP(?) TOP DW ? STACK ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA,ES:DATA,SS:STACK START: MOV AX,DATA MOV DS,AX MOV ES,AX MOV AX,STACK MOV SS,AX MOV SP,TOP MOV CX,WORD PTR ADDR[0] DEC CX LOOP1: MOV DI,CX MOV BX,2 LOOP2: MOV AX,WORD PTR ADDR[BX] CMP AX,WORD PTR ADDR[BX+2] JGE CCC XCHG AX,WORD PTR ADDR[BX+2] MOV WORD PTR ADDR[BX],AX CCC: ADD BX,2 LOOP LOOP2 MOV CX,DI LOOP LOOP1 EXIT: MOV AX,4C00H INT 21H CODE ENDS END START 五、实验结果如图: 六、心得体会:这次的实验比上次的稍微要复杂点,首先要先看懂程 序,在此程序中,用了一个循环,首先第一个数与第二个数相比较,然 后第三个数再与第一第二个数分别比较,依次类推 实验三 自编程序上机调试 一、实验目的 掌握用汇编语言编写排序程序的思路和方法。 二、实验内容 data segment x dw 600 y dw 25 z dw -2000 s dw ? data ends code segment assume ds:data,cs:code start:mov ax,data mov ds,ax mov
如果利用 `from` 和 `size` 进行分页查询可能会出现数据一致的情况。这是因为在 Elasticsearch 中,数据是分布式存储的,而分页查询是基于分片进行的。当一个查询跨越多个分片时,由于不同分片数据的不同,可能会导致数据一致的情况。 解决这个问题的方法是,使用 Search After API 来进行分页查询。Search After API 可以在查询结果中保留一个游标,可以在下一次查询中使用该游标来继续查询,从而确保数据一致性。 具体的做法是,在第一次查询时,使用 `sort` 参数对结果进行排序,并记录最后一条结果的排序值(可以是 `_id` 或其他字段)。在下一次查询时,使用 `search_after` 参数来指定排序值,以继续查询下一页数据。这样就可以确保每一页的数据是连续的,不会出现重复或遗漏的情况。 以下是使用 Search After API 进行分页查询的示例代码: ``` SearchRequest searchRequest = new SearchRequest("index_name"); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchSourceBuilder.query(QueryBuilders.matchAllQuery()); searchSourceBuilder.sort("_id", SortOrder.ASC); searchSourceBuilder.size(pageSize); if (page > 1) { // 使用 search_after 参数来指定排序值,以继续查询下一页 searchSourceBuilder.searchAfter(lastSortValues); } searchRequest.source(searchSourceBuilder); SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT); SearchHits hits = searchResponse.getHits(); if (hits.getTotalHits().value > 0) { SearchHit[] searchHits = hits.getHits(); for (SearchHit hit : searchHits) { // 处理查询结果 } // 记录最后一条结果的排序值,以供下一页查询使用 lastSortValues = searchHits[searchHits.length - 1].getSortValues(); } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值