Elasticsearch与.NET重新索引时滚动上下文超限及Scroll_id获取咨询
解决Elasticsearch重索引时滚动上下文超限问题
你遇到的Trying to create too many scroll contexts错误,本质是一次性启动了太多异步重索引任务,每个任务都会在ES内部打开scroll上下文;而你调用的ClearScrollAsync(c => c.ScrollId(default))只会清理已过期的scroll,对正在运行的重索引任务的scroll完全无效。另外,你没法直接拿到每个重索引任务对应的scroll id——因为Reindex后台任务的scroll是ES内部维护的,不会暴露给客户端。
给你几个可行的解决办法:
1. 控制重索引任务的并发数
用SemaphoreSlim限制同时运行的任务数量,避免一次性打开太多scroll上下文,数量建议略小于ES的search.max_open_scroll_context默认值(比如设为400),留足余量:
// 初始化信号量,限制并发数为400 var semaphore = new SemaphoreSlim(400); foreach( var destIndice in indiceDictionary.Keys ) { await semaphore.WaitAsync(); try { var reIndexResponse = await this._elasticSearchClient.Value.ReindexOnServerAsync(r => r .Source(src => src.Index(indiceDictionary[destIndice].ToArray())) .Destination(dest => dest.Index(destIndice)) .WaitForCompletion(false) ); var taskId = reIndexResponse.Task; this.logger.LogInformation("TriggerReorganization Reindex for dest {destinationIndice} with {numberOfSrcIndice} source indices has a Task with id : {taskId}" , destIndice, indiceDictionary[destIndice].Count, taskId); } finally { semaphore.Release(); } }
2. 等待单个任务完成后再启动下一个
如果业务对执行效率要求不高,可以在启动重索引任务后,调用WaitForTaskAsync等待任务完成,这样每个任务的scroll上下文会在任务结束后被ES自动清理,不会积累:
foreach( var destIndice in indiceDictionary.Keys ) { var reIndexResponse = await this._elasticSearchClient.Value.ReindexOnServerAsync(r => r .Source(src => src.Index(indiceDictionary[destIndice].ToArray())) .Destination(dest => dest.Index(destIndice)) .WaitForCompletion(false) ); var taskId = reIndexResponse.Task; this.logger.LogInformation("TriggerReorganization Reindex for dest {destinationIndice} with {numberOfSrcIndice} source indices has a Task with id : {taskId}" , destIndice, indiceDictionary[destIndice].Count, taskId); // 等待任务完成,确保scroll上下文被自动清理 await this._elasticSearchClient.Value.WaitForTaskAsync(taskId); }
3. 临时调整ES参数(不推荐长期使用)
如果上述方法暂时无法实施,可以临时调高search.max_open_scroll_context参数,缓解当前问题,但这只是权宜之计,长期来看还是要控制任务并发,避免ES资源过载:
PUT /_cluster/settings { "persistent": { "search.max_open_scroll_context": 1000 } }
注意:不要尝试手动清理正在运行的重索引任务的scroll,这会直接导致任务失败。ES会在重索引任务完成(无论成功或失败)后自动清理对应的scroll上下文,所以核心思路是控制同时运行的任务数量,避免超过限制。
内容的提问来源于stack exchange,提问作者Maxime Dousselaere
相关产品推荐
相关产品推荐

