Elasticsearch _search查询始终在每个索引上运行

时间:2018-11-28 15:06:47

标签: elasticsearch kibana

我在Kibana仪表板上遇到了问题,每次重新加载时都会抱怨多条Courier Fetch: xxx of 345 shards failed.警告消息。

好的,我要查询过去15分钟内的数据,并且每天都有一个索引。今天的索引不可能包含345个分片。那么,为什么我的查询会覆盖这么多碎片?


我检查过的东西:

  • 每个索引的索引数和分片数:

    我使用_cat/indices端点对此进行了检查:过滤掉我没有创建的索引(例如,kibana的索引,基本上所有以点开头的东西)之后,我有69个索引,每个索引包含5个分片(总共有345个分片)。那就是我所期望的。

    这基本上意味着我的搜索是对我的所有索引 all 执行的。

  • 我没有将新数据写入旧索引:

    这里是查询今天的索引 1 上一个小时的记录:

GET 20181027_logs/_search
{
"query": {
    "bool": {
      "must": [
        {
          "range": {
            "timestamp": {
              "gte": 1543326215000,
              "lte": 1543329815000,
              "format": "epoch_millis"
            }
          }
        }
      ]
    }
  }
}

答案(被截断):

{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 1557,

相同查询但不限制索引:

GET *_logs/_search
{
"query": {
    "bool": {
      "must": [
        {
          "range": {
            "timestamp": {
              "gte": 1543326215000,
              "lte": 1543329815000,
              "format": "epoch_millis"
            }
          }
        }
      ]
    }
  }
}

答案(被截断):

{
  "took": 24,
  "timed_out": false,
  "_shards": {
    "total": 345,
    "successful": 345,
    "failed": 0
  },
  "hits": {
    "total": 1557,

我们可以看到第二个查询返回的结果与第一个查询完全相同,但是会搜索每个索引。

  • 我的timestamp字段已编入索引:

    默认情况下,elasticsearch中的每个字段都已编入索引,但我仍然对其进行了仔细检查:

GET 20181027_logs/_mapping

{
  "20181027_logs": {
    "mappings": {
      "logs": {
        "properties": {
          […]
          "timestamp": {
            "type": "date"
          }
          […]

非索引字段将给出 2

           "timestamp": {
             "type": "date",
             "index": false
           }

剩余线索

目前,我真的不知道可能是什么问题。

请注意:时间戳记字段不是事件的插入日期,而是事件实际发生的日期。无论使用哪种时间戳,事件都将插入到最新索引中。 这意味着每个索引都可以有与过去日期相对应的事件,而没有将来的日期。

在这种情况下,我不知道这怎么回事:由于我们仅查询最近15分钟,因此无论发生什么情况,数据都只能位于最后一个索引中。

Elasticsearch和Kibana版本:5.4.3

感谢您阅读本文,任何帮助将不胜感激!


1:索引命名有误,导致索引名称与实际对应的日期之间存在偏移,但这在这里无关紧要。

2:这是在另一个具有相同版本的弹性簇上检查的,其中某些字段明确选择不进行索引编制

1 个答案:

答案 0 :(得分:2)

TL; DR

我终于通过减少分片的数量来解决了这个问题。

全面披露

在kibana上使用开发工具时,我在_msearch端点上发现很多错误:

{
  "shard": 2,
  "index": "20180909_logs",
  "node": "FCv8yvbyRhC9EPGLcT_k2w",
  "reason": {
    "type": "es_rejected_execution_exception",
    "reason": "rejected execution of org.elasticsearch.transport.TransportService$7@754fe283 on EsThreadPoolExecutor[search, queue capacity = 1000, org.elasticsearch.common.util.concurrent.EsThreadPoolExecutor@16a14433[Running, pool size = 7, active threads = 7, queued tasks = 1000, completed tasks = 16646]]"
  }
},

基本上可以证明我在ES服务器上向太多分片提供了太多并行请求。

据我了解,对于kibana而言,对我的索引模式的每个单个索引进行查询显然是正常的,如果其中一些不包含任何新鲜数据(ES应该仍然对它们进行查询,并得出结论,自从标记了时间戳字段以来,几乎没有任何时间包含任何数据)

从那里,我有几个选择:

  • 1:减少数据保留
  • 2:减少我正在执行的并行请求的数量
  • 3:将节点添加到我的集群中
  • 4:重组数据以使用更少的分片
  • 5:增加搜索队列的大小
在我的情况下,

1和2不是一个选择。

5可能会起作用,但是强烈建议不要这样做(据我所知,在大多数情况下,该错误只是更深层次问题的征兆,应予以解决)

这是一个160GB的单节点群集,具有(现在)超过350个分片。这使得每个分片的平均大小非常低,因此我决定首先尝试数字4:重新索引我的数据以使用更少的分片。

我如何用餐

每个索引使用一个分片:

我创建了以下索引模式:

PUT _template/logs {
  "template": "*_logs",
  "settings": {
    "number_of_shards": 1
  }
}

现在,我所有未来的索引将只有一个分片。

我仍然需要重新索引或合并现有索引,但是无论如何都必须在下一点上完成。

切换到月度索引(而不是每日)

我修改了将数据插入ES的代码,以使用基于月份的索引名称(例如201901_monthly_logs),然后将每个旧索引重新索引为新模式中的对应索引:

POST _reindex
{
  "source": {
    "index": "20181024_logs"
  },
  "dest": {
    "index": "201810_monthly_logs"
  }
}

享受!

这样做,我只剩下7个索引(也有7个分片)。 在我的kibana可视化中,剩下的就是将索引模式从_logs更改为_monthly_logs

自从这次以来我没有任何问题,我只需要再等一会,然后删除我的旧索引即可。