ES查询时索引延迟或更新导致数据不一致
当数据更新比较频繁时,我们短时间内使用相同的查询条件,得到的结果和记录数却不同。实际的业务要求查询的结果一致,以下是一些解决办法。
问题可能是由于Elasticsearch的索引延迟或更新造成的。可以考虑以下步骤来解决:
- 检查索引刷新率:确保索引的刷新率设置合理。默认情况下,Elasticsearch每秒刷新一次,但根据需要可能需要调整。
- 使用
search_type=dfs_query_then_fetch
:这确保查询使用全局词频,有助于提高结果的一致性。 - 使用时间点(PIT):为了在查询之间保持结果的一致性,可以使用PIT来保持索引的快照。
- 检查索引健康:确保没有正在进行的索引操作或问题影响查询结果。
本文说下2和3方案
使用 search_type=dfs_query_then_fetch
解释: search_type=dfs_query_then_fetch 是 Elasticsearch 的一种搜索模式,用于提高查询的准确性。在默认的 query_then_fetch 模式中,查询是按分片进行的,每个分片独立计算文档频率,然后将结果合并。但这可能会导致在频繁更新的情况下结果的不一致。 dfs_query_then_fetch 模式首先在所有分片上计算全局词频(Document Frequency),然后执行查询和排序。这使得查询和排序基于全局的词频信息,从而提供更一致的查询结果。
使用方法:
在查询请求中,你可以添加search_type=dfs_query_then_fetch
参数。例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
GET /your_index/_search?search_type=dfs_query_then_fetch
{
"query": {
"bool": {
"must": [
{
"range": {
"time": {
"from": "2024-08-14 08:00:00",
"to": "2024-08-15 08:00:00"
}
}
},
{
"term": {
"fileds1": "xxx"
}
},
{
"term": {
"fileds2": "xx"
}
}
]
}
},
"size": 0,
"aggs": {
"xsd_count": {
"terms": {
"field": "fileds1", //根据fileds1去重查询top5
"size": 5
}
},
"xsd_total": {
"cardinality": {
"field": "fileds1" //根据fileds1去重查询总数
}
}
}
}
使用时间点(PIT)
解释: 时间点(Point in Time, PIT)是一种在 Elasticsearch 中获取一致查询结果的机制。使用 PIT 可以在一个固定的索引快照上执行多个查询,确保查询结果在整个 PIT 生命周期内的一致性。 PIT 的主要优点是它允许在一个固定的时间点快照上进行多次查询,这样即使索引在查询期间发生了变化,查询结果依然会保持一致。(数据快照)
使用方法:
-
创建 PIT 首先,你需要创建一个 PIT。发送一个 POST 请求到 _pit 接口以创建 PIT,例如:
POST /_pit?keep_alive=1m
这将返回一个 PIT ID,你可以在后续查询中使用它。 - 使用 PIT 执行查询:
在查询请求中,添加 pit 参数和 PIT ID,例如:
1 2 3 4 5 6 7 8 9 10 11
GET /_search { "pit":{"id":"your_pit_id","keep_alive":"1m"}, "query":{ "bool":{ "must":[{ "range":{"time":{"from":"2024-08-14 08:00:00","to":"2024-08-15 08:00:59"}} }] } } }
- 关闭 PIT:
查询完成后,你可以关闭 PIT 以释放资源,例如:
DELETE /_pit?id=your_pit_id
在PIT id错误会返回错误:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"error": {
"root_cause": [
{
"type": "illegal_argument_exception",
"reason": "java.io.EOFException"
}
],
"type": "illegal_argument_exception",
"reason": "java.io.EOFException",
"caused_by": {
"type": "e_o_f_exception",
"reason": null
}
},
"status": 400
}
PIT id超过时间过期后返回错误:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
"error": {
"root_cause": [
{
"type": "search_context_missing_exception",
"reason": "No search context found for id [4635252]"
}],
"phase": "query",
"grouped": true,
"failed_shards": [
{
"shard": 0,
"index": "index-2022",
"node": "4sIEuxxxxxxxxxx",
"reason": {
"type": "search_context_missing_exception",
"reason": "No search context found for id [12345678]"
}
}],
"status": 404
}
}