Elasticsearch 6跨机器并行查询返回重复结果原因排查求助
这种情况我之前帮人排查过好几次,大概率是下面几个原因导致的,你可以逐一核对:
scroll_from参数完全一致:如果两台机器上的scroll_from变量设置了相同的值(比如都设为0),Elasticsearch会从同一个起始偏移位置返回数据,结果自然一模一样。要实现并行分页,你得给不同机器分配不同的起始偏移量,比如机器A用from_=0,机器B用from_=1000(假设每页取1000条),这样才能拿到不同批次的数据。没正确使用Scroll API的滚动机制:你现在的代码是直接调用
es.search()并携带scroll参数,但Scroll API的正确流程是:第一次调用search获取_scroll_id,后续每次调用es.scroll(scroll_id=获取到的ID, scroll=scroll_exp)来拉取下一批数据。如果两台机器都重复执行初始的search请求,而不是基于滚动ID续查,那每次都会返回第一页的内容,结果肯定相同。另外,Scroll API本身更适合批量遍历数据,并行处理的话,用**切片Scroll(Sliced Scroll)**会更靠谱。所有请求参数完全相同:除了
scroll_from,如果两台机器的body查询条件、size参数(没指定的话默认是10)都完全一致,Elasticsearch收到的是两个完全相同的查询请求,返回相同结果就不足为奇了。切片Scroll配置错误(如果尝试使用了):如果你本来想通过切片Scroll实现并行,但没给不同机器设置不同的切片参数,比如两台机器都用
{"slice": {"id": 0, "max": 2}},那它们还是会查询相同的数据分片。正确的做法是给机器A设slice.id=0、slice.max=2,机器B设slice.id=1、slice.max=2,这样两台机器会各自处理一半的数据,不会重复。
小建议
如果要并行批量获取ES数据,优先用切片Scroll,它会自动将数据分成多个独立切片,每个机器处理一个切片,能有效避免数据重复或遗漏。示例代码大概是这样:
# 机器A的代码 body = { "query": {...}, "slice": {"id": 0, "max": 2} } page = es.search(index=index, scroll=scroll_exp, sort="_doc", body=body) # 机器B的代码 body = { "query": {...}, "slice": {"id": 1, "max": 2} } page = es.search(index=index, scroll=scroll_exp, sort="_doc", body=body)
内容的提问来源于stack exchange,提问作者Djordje Zivanovic

