elasticsearch - Elasticsearch 索引中具有相同 _uid 的重复文档

标签 elasticsearch elasticsearch-2.0

我们在我们的一个 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

我们认为这是触发变化的原因:

  1. 当我们将索引从 ES 1.7 升级到 2.4 时,我们决定不就地升级 Elasticsearch,因为这会导致停机。相反,我们创建了一个单独的 ES 2.4 集群。

    我们使用复制所有索引设置和数据的工具将数据加载到新集群中,包括 version 设置 you should not set in ES 2.4 .

  2. 在处理最近的一个问题时,我们碰巧关闭并重新打开了索引。这通常会保留所有数据,但由于 version 设置不正确,导致 Elasticsearch 认为正在处理升级。

  3. 由于错误升级,ES 自动设置了 legacy.routing.hash.type 设置。这意味着在这一点之后索引的任何数据都使用旧的 DjbHashFunction 而不是最初用于路由数据的默认 Murmur3HashFunction

这意味着将数据重新索引到新索引中是解决问题的正确做法。新索引具有正确的版本设置并且没有遗留哈希函数设置:

"version": {
  "created": "2040699"
}

关于elasticsearch - Elasticsearch 索引中具有相同 _uid 的重复文档,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47082379/

相关文章:

elasticsearch - 如何分配实际未分配的碎片?

elasticsearch - 从文件路由行到持久 JMS 队列 : How to improve performance?

elasticsearch - 如何在 Elasticsearch 中使用 Liferay 7 搜索引擎 API?

elasticsearch - Elasticsearch-使用 “tags”索引发现给定字符串中的所有标签

elasticsearch - Elasticsearch脚本-将Unix时间戳转换为 “YYYYMM”

elasticsearch - ID查询中ID的最大数量是多少?

elasticsearch - 如何通过过滤查询获取某些字段中包含特定单词的文档?

elasticsearch - more_like_this不适用于字段中重复的相同文本

elasticsearch - elasticsearch _update_by_query不起作用

elasticsearch - Elasticsearch 分组依据,过滤器不起作用