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

时间:2017-11-02 18:36:49

标签: 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依次在每个分片上运行上面的聚合查询来验证这一点:它没有在单个分片中找到任何重复项。

我们最好的猜测是路由出现了问题,但我们并不了解副本如何路由到不同的分片。根据{{​​3}},默认路由基于文档ID,并且应始终将文档路由到同一个分片。

我们没有使用会覆盖默认路由的自定义路由参数。我们通过确保重复文件没有_routing字段来对此进行双重检查。

我们也没有定义任何也会影响路由的父/子关系。 (例如,请参阅routing documentation,其症状与我们的问题相同。我们不会认为原因是相同的,因为我们没有设置任何文件父母。)

我们通过重新索引到新索引来解决当前问题,该索引压缩了重复文档。我们仍然有旧索引进行调试。

我们还没有找到一种复制问题的方法。新索引正在正确索引文档,我们已经尝试重新运行隔夜处理作业,该作业也会更新文档,但它还没有创建任何重复文件。

群集有3个节点,3个主分片和1个副本(即3个副本分片)。 minimum_master_nodes设置为2,这可能会阻止this question in the Elasticsearch forum问题。我们正在运行Elasticsearch 2.4(我们知道它已经过时了 - 我们计划很快升级)。

有谁知道可能导致这些重复的原因?您对调试方法有什么建议吗?

1 个答案:

答案 0 :(得分:3)

我们找到了答案!问题是索引意外地切换了它用于路由的散列算法,这导致一些更新的文档存储在不同的分片上,原始版本。

/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集群。

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

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

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

  4. 这意味着将数据重新索引到新索引是解决问题的正确方法。新索引具有正确的版本设置,并且没有旧版散列函数设置:

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