Elasticsearch _search 查询始终在每个索引上运行
Elasticsearch _search query always runs on every index
我在使用 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,
我们可以看到第二个查询 returns 与第一个查询的结果完全相同,但是搜索了每个索引。
我的 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:这是在另一个相同版本的弹性集群上检查的,其中一些字段明确选择退出索引
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@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
。
这次我没有遇到任何问题,我再等一下,然后删除我的旧索引。
我在使用 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,
我们可以看到第二个查询 returns 与第一个查询的结果完全相同,但是搜索了每个索引。
我的
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:这是在另一个相同版本的弹性集群上检查的,其中一些字段明确选择退出索引
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@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
。
这次我没有遇到任何问题,我再等一下,然后删除我的旧索引。