我们在其中一个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(我们知道它已经过时了 - 我们计划很快升级)。
有谁知道可能导致这些重复的原因?您对调试方法有什么建议吗?
答案 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
我们认为这是触发变革的原因:
当我们将索引从ES 1.7升级到2.4时,我们决定不在适当的位置升级Elasticsearch,因为这会导致停机。相反,我们创建了一个单独的ES 2.4集群。
我们使用复制了所有索引设置和数据的工具将数据加载到新群集中,其中包括you should not set in ES 2.4的version
设置。
在处理最近的问题时,我们碰巧关闭并重新打开索引。这通常会保留所有数据,但由于version
设置不正确,导致Elasticsearch认为正在处理升级。
由于错误升级,ES会自动设置legacy.routing.hash.type
设置。这意味着在此点之后索引的任何数据都使用旧DjbHashFunction
而不是最初用于路由数据的默认Murmur3HashFunction
。
这意味着将数据重新索引到新索引是解决问题的正确方法。新索引具有正确的版本设置,并且没有旧版散列函数设置:
"version": {
"created": "2040699"
}