[英]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.