异步查询的需求背景
在日常 ES 开发与运维中,同步查询是最常用的方式,但在以下场景中,同步查询会暴露明显短板,进而催生了异步查询的需求:
-
大数据量查询场景:当查询结果集庞大(如单次查询 10 万条以上数据)、查询条件复杂(多字段聚合、深度嵌套查询)时,同步查询需要等待所有结果计算完成后才能返回响应,耗时极长,容易导致客户端请求超时、连接中断,甚至占用大量集群资源,影响其他业务查询的正常执行。
-
高并发查询场景:在高并发业务中,大量同步查询请求同时发起,会导致 ES 协调节点、数据节点负载飙升,引发 GC 频繁、响应延迟,严重时会造成集群不稳定,无法支撑业务的高可用需求。
-
非实时性需求场景:部分业务对查询结果的实时性要求不高(如离线统计、数据导出、批量分析),无需等待查询立即完成,此时异步查询可将查询任务后台执行,客户端后续按需获取结果,避免长时间阻塞。
-
长耗时查询场景:对于跨多个索引、跨节点的联合查询,或需要大量计算的聚合查询,同步查询的等待时间可能远超业务容忍范围,异步查询可有效规避这一问题,提升业务体验。
简言之,异步查询的核心需求的是:在不影响集群稳定性、不阻塞客户端的前提下,高效处理长耗时、大数据量的查询任务,实现查询任务的后台化、可控化。
异步查询的基本原理
ES 异步查询的核心逻辑是"请求提交-后台执行-结果缓存-按需获取",彻底打破同步查询"请求发起后必须等待结果返回"的阻塞模式,具体原理可分为以下 4 个步骤:
-
提交异步查询请求 :客户端向 ES 提交异步查询请求时,通过指定
wait_for_completion_timeout参数(设置极短时间,如 1ms),告知 ES 无需等待查询完成,直接返回一个唯一的查询 ID(async_search_id),此时查询任务被提交到 ES 集群后台执行。 -
后台执行查询任务:ES 集群接收查询任务后,由协调节点分配任务到对应的数据节点,数据节点并行执行查询、计算结果,整个过程在后台完成,不阻塞客户端的后续操作,客户端可正常处理其他业务逻辑。
-
结果缓存与有效期管理:查询任务执行完成后,ES 会将查询结果缓存到集群中,默认缓存有效期为 5 天(可通过参数调整)。缓存的结果包括查询匹配的文档、聚合结果等,方便客户端后续通过查询 ID 快速获取。
-
按需获取查询结果:客户端获取到查询 ID 后,可在任意时间通过该 ID 发起请求,获取查询结果;若查询尚未执行完成,ES 会返回当前查询的进度;若查询已完成,直接返回缓存的结果;若结果已过期,ES 会提示重新发起查询。
补充说明:异步查询的底层依赖 ES 的 Scroll 机制实现数据遍历,同时通过缓存机制避免重复执行查询,既保证了大数据量查询的效率,又减少了集群资源的浪费。与同步查询相比,异步查询将"阻塞等待"转化为"异步触发+按需获取",大幅提升了客户端的响应速度和集群的并发处理能力。
异步查询的实战演示:
POST page_study_index/_async_search?wait_for_completion_timeout=1ms
{
"track_total_hits": true,
"query": {
"match_all": {}
},
"size":100000,
"sort": [
{
"number": {
"order": "desc"
}
}
]
}
GET _async_search/FklMSnZpWFYzUUU2RmlZUlk4dDZOOVEdbmZWM1YwaEJSUVNSenVIeUxyazBGUToxNTQ1MTA
异步查询默认最大返回 10MB 数据,手动调大上限会让 ES 节点占用大量内存,引发 GC 卡顿、负载过高,严重破坏集群稳定性,因此生产环境不建议调整。
临时修改(集群动态生效,重启失效)
json
PUT /_cluster/settings
{
"persistent": {
"search.max_async_search_response_size": "50mb"
}
}
2. 永久修改(需改配置文件,重启节点生效)
在 elasticsearch.yml 中添加:
search.max_async_search_response_size: 50mb
默认缓存的有效期是5天,我们可以通过参数进行调整:
POST page_study_index/_async_search?wait_for_completion_timeout=1ms&keep_alive=1m
{
"track_total_hits": true,
"query": {
"match_all": {}
},
"size":100000,
"sort": [
{
"number": {
"order": "desc"
}
}
]
}