<div class="content" id="articleContent"> <div class="ad-wrap" xongsyz="" hidden=""> <p style="margin:0 0 10px 0;"><a data-traceid="blog_detail_above_text_link_1" data-tracepid="blog_detail_above_text_link" style="color:#A00;font-weight:bold;" href="https://my.oschina.net/u/2663968/blog/3041208" target="_blank" xongsyz="" hidden="">面試:你懂什麼是分佈式系統嗎?Redis分佈式鎖都不會?>>> </a> <img src="https://www.oschina.net/img/hot3.png" align="absmiddle" style="max-height: 32px; max-width: 32px;"></p> </div> <p>The best elasticsearch highlevel java rest api-----<a href="https://www.oschina.net/p/bboss-elastic" target="_blank" rel="nofollow">bboss</a> </p> <p>Elasticsearch Sliced Scroll分頁檢索案例分享 </p> <p>咱們在文章《<a href="https://my.oschina.net/bboss/blog/1786493" target="_blank" rel="nofollow">Elasticsearch Scroll分頁檢索案例分享</a>》中介紹了elasticsearch scroll的基本用法,本文介紹Elasticsearch Sliced Scroll分頁檢索功能。</p> <span id="OSC_h1_1"></span> <h1 id="h1_1">1.準備工做</h1> <p>參考文檔《<a href="https://my.oschina.net/bboss/blog/1556866" target="_blank" rel="nofollow">高性能elasticsearch ORM開發庫使用介紹</a>》導入和配置es客戶端</p> <span id="OSC_h1_2"></span> <h1 id="h1_2">2.定義Sliced Scroll檢索dsl</h1> <p>建立配置文件-在resources目錄下定義文件scroll.xml</p> <pre>esmapper/scroll.xml</pre> <p>文件內容包含Sliced Scroll檢索dsl語句-scrollSliceQuery</p> <pre><code class="hljs xml"><span class="hljs-tag"><<span class="hljs-name">property</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"scrollSliceQuery"</span>></span> <![CDATA[ { "slice": { "id": $id, "max": $max }, "size":$size, "query": { "term" : { "gc.jvmGcOldCount" : 3 } } } ]]> <span class="hljs-tag"></<span class="hljs-name">property</span>></span></code></pre> <span id="OSC_h1_3"></span> <h1 id="h1_3">3.串行方式執行slice檢索</h1> <pre><code class="hljs java"><span class="hljs-comment">/** * 串行方式執行slice scroll操做 */</span> <span class="hljs-meta">@Test</span> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testSliceScroll</span><span class="hljs-params">()</span> </span>{ ClientInterface clientUtil = ElasticSearchHelper.getConfigRestClientUtil(<span class="hljs-string">"esmapper/scroll.xml"</span>); List<String> scrollIds = <span class="hljs-keyword">new</span> ArrayList<>(); <span class="hljs-keyword">long</span> starttime = System.currentTimeMillis(); <span class="hljs-comment">//scroll slice分頁檢索</span> <span class="hljs-keyword">int</span> max = <span class="hljs-number">6</span>; <span class="hljs-keyword">long</span> realTotalSize = <span class="hljs-number">0</span>; <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < max; i++) { Map params = <span class="hljs-keyword">new</span> HashMap(); params.put(<span class="hljs-string">"id"</span>, i); params.put(<span class="hljs-string">"max"</span>, max);<span class="hljs-comment">//最多6個slice,不能大於share數</span> params.put(<span class="hljs-string">"size"</span>, <span class="hljs-number">100</span>);<span class="hljs-comment">//每頁100條記錄</span> ESDatas<Map> sliceResponse = clientUtil.searchList(<span class="hljs-string">"agentstat-*/_search?scroll=1m"</span>, <span class="hljs-string">"scrollSliceQuery"</span>, params,Map.class); List<Map> sliceDatas = sliceResponse.getDatas(); realTotalSize = realTotalSize + sliceDatas.size(); <span class="hljs-keyword">long</span> totalSize = sliceResponse.getTotalSize(); String scrollId = sliceResponse.getScrollId(); <span class="hljs-keyword">if</span> (scrollId != <span class="hljs-keyword">null</span>) scrollIds.add(scrollId); System.out.println(<span class="hljs-string">"totalSize:"</span> + totalSize); System.out.println(<span class="hljs-string">"scrollId:"</span> + scrollId); <span class="hljs-keyword">if</span> (sliceDatas != <span class="hljs-keyword">null</span> && sliceDatas.size() >= <span class="hljs-number">100</span>) {<span class="hljs-comment">//每頁100條記錄,迭代scrollid,遍歷scroll分頁結果</span> <span class="hljs-keyword">do</span> { sliceResponse = clientUtil.searchScroll(<span class="hljs-string">"1m"</span>, scrollId, Map.class); String sliceScrollId = sliceResponse.getScrollId(); <span class="hljs-keyword">if</span> (sliceScrollId != <span class="hljs-keyword">null</span>) scrollIds.add(sliceScrollId); sliceDatas = sliceResponse.getDatas(); <span class="hljs-keyword">if</span> (sliceDatas == <span class="hljs-keyword">null</span> || sliceDatas.size() < <span class="hljs-number">100</span>) { <span class="hljs-keyword">break</span>; } realTotalSize = realTotalSize + sliceDatas.size(); } <span class="hljs-keyword">while</span> (<span class="hljs-keyword">true</span>); } } <span class="hljs-comment">//打印處理耗時和實際檢索到的數據</span> <span class="hljs-keyword">long</span> endtime = System.currentTimeMillis(); System.out.println(<span class="hljs-string">"耗時:"</span>+(endtime - starttime)+<span class="hljs-string">",realTotalSize:"</span>+realTotalSize); <span class="hljs-comment">//查詢存在es服務器上的scroll上下文信息</span> String scrolls = clientUtil.executeHttp(<span class="hljs-string">"_nodes/stats/indices/search"</span>, ClientUtil.HTTP_GET); System.out.println(scrolls); <span class="hljs-comment">//處理完畢後清除scroll上下文信息</span> <span class="hljs-keyword">if</span>(scrollIds.size() > <span class="hljs-number">0</span>) { scrolls = clientUtil.deleteScrolls(scrollIds); System.out.println(scrolls); } <span class="hljs-comment">//清理完畢後查看scroll上下文信息</span> scrolls = clientUtil.executeHttp(<span class="hljs-string">"_nodes/stats/indices/search"</span>, ClientUtil.HTTP_GET); System.out.println(scrolls); }</code></pre> <span id="OSC_h1_4"></span> <h1 id="h1_4">4.並行方式執行slice檢索</h1> <pre><code class="hljs java"><span class="hljs-comment">//用來存放實際slice檢索總記錄數</span> <span class="hljs-keyword">long</span> realTotalSize ; <span class="hljs-comment">//輔助方法,用來累計每次scroll獲取到的記錄數</span> <span class="hljs-function"><span class="hljs-keyword">synchronized</span> <span class="hljs-keyword">void</span> <span class="hljs-title">incrementSize</span><span class="hljs-params">(<span class="hljs-keyword">int</span> size)</span></span>{ <span class="hljs-keyword">this</span>.realTotalSize = <span class="hljs-keyword">this</span>.realTotalSize + size; } <span class="hljs-comment">/** * 並行方式執行slice scroll操做 */</span> <span class="hljs-meta">@Test</span> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testParralSliceScroll</span><span class="hljs-params">()</span> </span>{ <span class="hljs-keyword">final</span> ClientInterface clientUtil = ElasticSearchHelper.getConfigRestClientUtil(<span class="hljs-string">"esmapper/scroll.xml"</span>); <span class="hljs-keyword">final</span> List<String> scrollIds = <span class="hljs-keyword">new</span> ArrayList<>(); <span class="hljs-keyword">long</span> starttime = System.currentTimeMillis(); <span class="hljs-comment">//scroll slice分頁檢索</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> max = <span class="hljs-number">6</span>; <span class="hljs-keyword">final</span> CountDownLatch countDownLatch = <span class="hljs-keyword">new</span> CountDownLatch(max);<span class="hljs-comment">//線程任務完成計數器,每一個線程對應一個sclice,每運行完一個slice任務,countDownLatch計數減去1</span>html
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = <span class="hljs-number">0</span>; j < max; j++) {<span class="hljs-comment">//啓動max個線程,並行處理每一個slice任務</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">int</span> i = j; Thread sliceThread = <span class="hljs-keyword">new</span> Thread(<span class="hljs-keyword">new</span> Runnable() {<span class="hljs-comment">//多線程並行執行scroll操做作,每一個線程對應一個sclice</span> <span class="hljs-meta">@Override</span> <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">run</span><span class="hljs-params">()</span> </span>{ Map params = <span class="hljs-keyword">new</span> HashMap(); params.put(<span class="hljs-string">"id"</span>, i); params.put(<span class="hljs-string">"max"</span>, max);<span class="hljs-comment">//最多6個slice,不能大於share數</span> params.put(<span class="hljs-string">"size"</span>, <span class="hljs-number">100</span>);<span class="hljs-comment">//每頁100條記錄</span> ESDatas<Map> sliceResponse = clientUtil.searchList(<span class="hljs-string">"agentstat-*/_search?scroll=1m"</span>, <span class="hljs-string">"scrollSliceQuery"</span>, params,Map.class); List<Map> sliceDatas = sliceResponse.getDatas(); incrementSize( sliceDatas.size());<span class="hljs-comment">//統計實際處理的文檔數量</span> <span class="hljs-keyword">long</span> totalSize = sliceResponse.getTotalSize(); String scrollId = sliceResponse.getScrollId(); <span class="hljs-keyword">if</span> (scrollId != <span class="hljs-keyword">null</span>) scrollIds.add(scrollId); System.out.println(<span class="hljs-string">"totalSize:"</span> + totalSize); System.out.println(<span class="hljs-string">"scrollId:"</span> + scrollId); <span class="hljs-keyword">if</span> (sliceDatas != <span class="hljs-keyword">null</span> && sliceDatas.size() >= <span class="hljs-number">100</span>) {<span class="hljs-comment">//每頁100條記錄,迭代scrollid,遍歷scroll分頁結果</span> <span class="hljs-keyword">do</span> { sliceResponse = clientUtil.searchScroll(<span class="hljs-string">"1m"</span>, scrollId, Map.class); String sliceScrollId = sliceResponse.getScrollId(); <span class="hljs-keyword">if</span> (sliceScrollId != <span class="hljs-keyword">null</span>) scrollIds.add(sliceScrollId); sliceDatas = sliceResponse.getDatas(); <span class="hljs-keyword">if</span> (sliceDatas == <span class="hljs-keyword">null</span> || sliceDatas.size() < <span class="hljs-number">100</span>) { <span class="hljs-keyword">break</span>; } incrementSize( sliceDatas.size());<span class="hljs-comment">//統計實際處理的文檔數量</span> } <span class="hljs-keyword">while</span> (<span class="hljs-keyword">true</span>); } countDownLatch.countDown();<span class="hljs-comment">//slice檢索完畢後計數器減1</span> } }); sliceThread.start();<span class="hljs-comment">//啓動線程</span> } <span class="hljs-keyword">try</span> { countDownLatch.await();<span class="hljs-comment">//等待全部的線程執行完畢,計數器變成0</span> } <span class="hljs-keyword">catch</span> (InterruptedException e) { e.printStackTrace(); } <span class="hljs-comment">//打印處理耗時和實際檢索到的數據</span> <span class="hljs-keyword">long</span> endtime = System.currentTimeMillis(); System.out.println(<span class="hljs-string">"耗時:"</span>+(endtime - starttime)+<span class="hljs-string">",realTotalSize:"</span>+realTotalSize); <span class="hljs-comment">//查詢存在es服務器上的scroll上下文信息</span> String scrolls = clientUtil.executeHttp(<span class="hljs-string">"_nodes/stats/indices/search"</span>, ClientUtil.HTTP_GET);
<span class="hljs-comment">// System.out.println(scrolls);</span> <span class="hljs-comment">//處理完畢後清除scroll上下文信息</span> <span class="hljs-keyword">if</span>(scrollIds.size() > <span class="hljs-number">0</span>) { scrolls = clientUtil.deleteScrolls(scrollIds); <span class="hljs-comment">// System.out.println(scrolls);</span> } <span class="hljs-comment">//清理完畢後查看scroll上下文信息</span> scrolls = clientUtil.executeHttp(<span class="hljs-string">"_nodes/stats/indices/search"</span>, ClientUtil.HTTP_GET); <span class="hljs-comment">// System.out.println(scrolls);</span> }</code></pre>java
<p>經過串行運行和並行運行結果比較,並行處理的性能要好不少,實際檢索到的文檔數量等價一致。</p> <span id="OSC_h1_5"></span> <h1 id="h1_5">5.參考文檔</h1> <p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/6.2/search-request-scroll.html" target="_blank" rel="nofollow">https://www.elastic.co/guide/en/elasticsearch/reference/6.2/search-request-scroll.html</a></p> <span id="OSC_h1_6"></span> <h1 id="h1_6">6.開發交流</h1> <p>elasticsearch技術交流羣:166471282</p> <div class="ad-wrap" style="margin-top: 12px;" xongsyz="" hidden=""> <div id="blog-title-ad" data-traceid="blog_ali" data-tracepid="blogdown" style=""> <script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> <!-- 博客詳情頁下方 --> <ins class="adsbygoogle" style="display:inline-block;width:728px;height:90px" data-ad-client="ca-pub-7090564139599510" data-ad-slot="2321828009" xongsyz="" hidden=""></ins> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script> </div>node
<!-- <script> function success_jsonpCallback(data) { var obj = eval(data); if( obj.success ){ var contents = eval(obj.data[0].content); if(contents.length > 0){ var content = contents[0]; $('#blog-title-ad').prepend("<a href='"+ content.url +"' target='_blank' style='max-width:780px;'><img src='"+content.img+"'/></a>"); $('#blog-title-ad').show(); } }else { $('#blog-title-ad').hide(); } } window.addEventListener("load", function() { var url=" http://clickc.admaster.com.cn/c/a116493,b2949390,c3159,i0,m101,8a1,8b2,h"; $.ajax({ type: 'POST', url: url, jsonp: "callback", dataType: 'jsonp', jsonpCallback: 'success_jsonpCallback', contentType: "application/json; charset=utf-8", success: function( response ) { // do in callback }, error:function(){ $('#blog-title-ad').hide(); } }); }, false); </script> -->面試
</div> </div>