我们在我们的一个 Elasticsearch 索引中发现了一些重复的文档,但我们无法找出原因。每个受影响的文档都有两个副本,它们具有完全相同的 _id
、_type
和 _uid
字段。
对 /index-name/document-type/document-id
的 GET 请求只返回一个副本,但是用这样的查询搜索文档会返回两个结果,这很令人惊讶:
POST /index-name/document-type/_search
{
"filter": {
"term": {
"_id": "document-id"
}
}
}
在 _uid
字段上聚合也可以识别重复文档:
POST /index-name/_search
{
"size": 0,
"aggs": {
"duplicates": {
"terms": {
"field": "_uid",
"min_doc_count": 2
}
}
}
}
重复项都在不同的分片上。例如,一个文档可能在主分片 0 上有一个副本,在主分片 1 上有一个副本。我们已经通过使用 preference parameter 在每个分片上依次运行上面的聚合查询来验证这一点。 : 它没有在单个分片中找到任何重复项。
我们最好的猜测是路由出了问题,但我们不明白副本是如何路由到不同的分片的。根据routing documentation ,默认路由基于文档 ID,并且应该一致地将文档路由到同一个分片。
我们没有使用会覆盖默认路由的自定义路由参数。我们通过确保重复文档没有 _routing
字段来仔细检查这一点。
我们也没有定义任何也会影响路由的父/子关系。 (例如,参见 this question in the Elasticsearch forum ,它与我们的问题具有相同的症状。我们认为原因不同,因为我们没有设置任何文档父级)。
我们通过重新索引到一个新的索引来解决眼前的问题,该索引压缩了重复的文档。我们仍有旧索引可供调试。
我们还没有找到重现该问题的方法。新索引正确地索引了文档,我们已经尝试重新运行通宵处理作业,该作业也会更新文档,但它没有创建更多重复项。
集群有 3 个节点,3 个主分片和 1 个副本(即 3 个副本分片)。 minimum_master_nodes
设置为 2,这应该可以防止 split-brain问题。我们正在运行 Elasticsearch 2.4(我们知道它很旧 - 我们计划很快升级)。
有谁知道可能导致这些重复项的原因是什么?您对调试方法有什么建议吗?
最佳答案
我们找到了答案!问题是索引意外地切换了它用于路由的哈希算法,这导致一些更新的文档存储在不同的分片上,成为它们的原始版本。
对 /index-name/_settings
的 GET 请求揭示了这一点:
"version": {
"created": "1070599",
"upgraded": "2040699"
},
"legacy": {
"routing": {
"use_type": "false",
"hash": {
"type": "org.elasticsearch.cluster.routing.DjbHashFunction"
}
}
}
“1070599”是指Elasticsearch 1.7,“2040699”是ES 2.4。
看起来索引试图将自己从 1.7 升级到 2.4,尽管事实上它已经在运行 2.4。这是此处描述的问题:https://github.com/elastic/elasticsearch/issues/18459#issuecomment-220313383
我们认为这是触发变化的原因:
当我们将索引从 ES 1.7 升级到 2.4 时,我们决定不就地升级 Elasticsearch,因为这会导致停机。相反,我们创建了一个单独的 ES 2.4 集群。
我们使用复制所有索引设置和数据的工具将数据加载到新集群中,包括
version
设置 you should not set in ES 2.4 .在处理最近的一个问题时,我们碰巧关闭并重新打开了索引。这通常会保留所有数据,但由于
version
设置不正确,导致 Elasticsearch 认为正在处理升级。由于错误升级,ES 自动设置了
legacy.routing.hash.type
设置。这意味着在这一点之后索引的任何数据都使用旧的DjbHashFunction
而不是最初用于路由数据的默认Murmur3HashFunction
。
这意味着将数据重新索引到新索引中是解决问题的正确做法。新索引具有正确的版本设置并且没有遗留哈希函数设置:
"version": {
"created": "2040699"
}
关于elasticsearch - Elasticsearch 索引中具有相同 _uid 的重复文档,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47082379/