[英]ElasticSearch Scroll API with multi threading
首先,我想让大家知道我知道ElasticSearch Scroll API如何工作的基本工作逻辑。 要使用Scroll API,首先,我们需要使用一些滚动值(如1m )调用search方法,然后它将返回一个_scroll_id ,它将用于 Scroll 上的下一个连续调用,直到所有文档在循环内返回。 但问题是我只想在多线程的基础上使用相同的进程,而不是串行。 例如:
如果我有 300000 个文档,那么我想以这种方式处理/获取文档
所以我的问题是,我没有找到任何方法来设置滚动 API 上的from值,如何使用线程使滚动过程更快。 不要以序列化的方式处理文档。
我的示例 python 代码
if index_name is not None and doc_type is not None and body is not None:
es = init_es()
page = es.search(index_name,doc_type, scroll = '30s',size = 10, body = body)
sid = page['_scroll_id']
scroll_size = page['hits']['total']
# Start scrolling
while (scroll_size > 0):
print("Scrolling...")
page = es.scroll(scroll_id=sid, scroll='30s')
# Update the scroll ID
sid = page['_scroll_id']
print("scroll id: " + sid)
# Get the number of results that we returned in the last scroll
scroll_size = len(page['hits']['hits'])
print("scroll size: " + str(scroll_size))
print("scrolled data :" )
print(page['aggregations'])
你试过切片卷轴吗? 根据链接的文档:
对于返回大量文档的滚动查询,可以将滚动拆分为可以独立使用的多个切片。
和
每个滚动都是独立的,可以像任何滚动请求一样并行处理。
我自己没有使用过这个(我需要处理的最大结果集是 ~50k 文档),但这似乎是你正在寻找的。
您应该为此使用切片滚动,请参阅https://github.com/elastic/elasticsearch-dsl-py/issues/817#issuecomment-372271460了解如何在 python 中执行此操作。
滚动必须是同步的,这是逻辑。
您可以使用多线程,这正是 elasticsearch 适合的原因:并行性。
一个弹性搜索索引,由分片组成,这是您数据的物理存储。 分片可以在同一个节点上,也可以不在(更好)。
另一方面,搜索 API 提供了一个非常好的选项: _preference
( https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-preference.html )
所以回到你的应用程序:
等等!
此外,您可以使用 elasticsearch4hadoop 插件,它对 Spark / PIG / map-reduce / Hive 完全相同。
我遇到了和你一样的问题,但文档大小是 140 万。 我不得不使用并发方法并使用 10 个线程进行数据写入。
我用Java线程池写了代码,你可以在Python中找到类似的方式。
public class ControllerRunnable implements Runnable {
private String i_res;
private String i_scroll_id;
private int i_index;
private JSONArray i_hits;
private JSONObject i_result;
ControllerRunnable(int index_copy, String _scroll_id_copy) {
i_index = index_copy;
i_scroll_id = _scroll_id_copy;
}
@Override
public void run(){
try {
s_logger.debug("index:{}", i_index );
String nexturl = m_scrollUrl.replace("--", i_scroll_id);
s_logger.debug("nexturl:{}", nexturl);
i_res = get(nexturl);
s_logger.debug("i_res:{}", i_res);
i_result = JSONObject.parseObject(i_res);
if (i_result == null) {
s_logger.info("controller thread parsed result object NULL, res:{}", i_res);
s_counter++;
return;
}
i_scroll_id = (String) i_result.get("_scroll_id");
i_hits = i_result.getJSONObject("hits").getJSONArray("hits");
s_logger.debug("hits content:{}\n", i_hits.toString());
s_logger.info("hits_size:{}", i_hits.size());
if (i_hits.size() > 0) {
int per_thread_data_num = i_hits.size() / s_threadnumber;
for (int i = 0; i < s_threadnumber; i++) {
Runnable worker = new DataRunnable(i * per_thread_data_num,
(i + 1) * per_thread_data_num);
m_executor.execute(worker);
}
// Wait until all threads are finish
m_executor.awaitTermination(1, TimeUnit.SECONDS);
} else {
s_counter++;
return;
}
} catch (Exception e) {
s_logger.error(e.getMessage(),e);
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.