Elasticsearch ingest pipeline配合update_by_query触发版本冲突异常
场景
为现有ingest pipeline配置了作用于全管道的on_failure规则,具体配置如下:
"on_failure" : [ { "set" : { "field" : "_index", "value" : "failed-{{ _index }}" } }, { "set" : { "field" : "caused_by", "value" : "{{ _ingest.on_failure_message }}" } } ]
问题描述
上述ingest pipeline用于配合update_by_query API完成文档富化操作,预期管道触发失败时,失败文档会被路由至指定的失败索引(格式为failed-原索引名),但实际操作中无法实现该路由逻辑,执行返回的具体报错如下:
{ "took": 276, "timed_out": false, "total": 1, "updated": 0, "deleted": 0, "batches": 1, "version_conflicts": 1, "noops": 0, "retries": { "bulk": 0, "search": 0 }, "throttled_millis": 0, "requests_per_second": -1, "throttled_until_millis": 0, "failures": [ { "index": "failed-my_index", "type": "_doc", "id": "1002109", "cause": { "type": "version_conflict_engine_exception", "reason": "[1002109]: version conflict, required seqNo [37265539], primary term [20]. but no document was found", "index_uuid": "JMepgCegQamU8WDqQuFJ3Q", "shard": "0", "index": "failed-my_index" }, "status": 409 } ] }
结合报错逻辑可以确认:文档1002109最初写入原索引时并未触发管道失败,因此不存在于failed-my_index中。执行更新操作时管道触发失败,需要将该文档写入失败索引,但当前抛出的version_conflict_engine_exception报错直接阻断了整个写入流程。
配置存在的核心问题
update_by_query属于读-改-写类操作,执行过程中会严格携带原索引中目标文档的版本元数据(包括版本号、seqNo、primary term)发起后续写入请求,不会因为ingest pipeline中修改了_index路由字段就自动重置这些元数据。
当on_failure逻辑将目标索引切换为失败索引时,携带的版本元数据仍然来自原索引,而这套元数据在全新的目标失败索引中不存在匹配的文档,Elasticsearch就会触发409版本冲突校验,直接拒绝写入请求,导致失败文档无法落地到指定索引。
调整方向
在on_failure的处理逻辑中,补充对版本元数据的清理步骤,明确告知Elasticsearch该请求为全新写入操作,无需执行原有的版本校验:
"on_failure" : [ { "set" : { "field" : "_index", "value" : "failed-{{ _index }}" } }, // 清理原有版本元数据的新增逻辑 { "remove": { "field": ["_version", "_seq_no", "_primary_term"], "ignore_missing": true } }, { "set" : { "field" : "caused_by", "value" : "{{ _ingest.on_failure_message }}" } } ]
内容的提问来源于stack exchange,提问作者Muhammad Ali
相关产品推荐
相关产品推荐

