es的java客戶端代碼(java 連接es)

本文目錄一覽:

Java代碼查詢es 的索引是yellow的狀態,怎麼可以查詢不報錯?

建議提前檢查,為yellow直接提醒運維去維護為green。不過我這邊用的es6.2.3yellow是正常查詢的。建議你檢查一下環境配置應該不是yellow的問題。試了一下;為red都可以正常查詢的(java代碼查詢結果和下圖es-head查詢結果一致)

怎麼用spring獲取es數據

1. ES和solr都是作為全文搜索引擎出現的。都是基於Lucene的搜索服務器。

2. ES不是可靠的存儲系統,不是數據庫,它有丟數據的風險。

3. ES不是實時系統,數據寫入成功只是trans log成功(類似於MySQL的bin log),寫入成功後立刻查詢查不到是正常的。因為數據此刻可能還在內存里而不是進入存儲引擎里。同理,刪除一條數據後也不是馬上消失。寫入何時可查詢?ES內部有一個後台線程,定時將內存中的一批數據寫入到存儲引擎,此後數據可見。默認後台線程一秒運行一次。該線程運行的越頻繁,寫入性能越低。運行的頻率越低,寫入的性能越高(不會無限高)。

4. 目前已知的單ES集群可以存儲PB級別的數據,不過這個就非常費勁了。TB級別數據沒壓力。

5. 如果使用ES官方提供的jar包訪問,需要JDK1.7及以上。

6. 使用對應的版本訪問ES server。如果ES server端的版本是1.7,那麼請使用ES 1.7的client。如果ES server是2.1,請使用2.1的client。

7. ES索引存在Linux服務器的文件系統之上(背後是文件系統,不是類似於HDFS的分佈式文件系統)

8. ES Java client是線程安全的,全局構建一個即可滿足讀寫需求,不要每次都創建ES client。每次訪問ES都構建新的es client即會拋出次異常。

9. 非常不建議使用ES的動態識別和創建的機制,因為很多情況下這並非你所需要。推薦的做法是在寫數據之前仔細的創建mapping。

10. 強烈不建議在ES中使用深分頁。可能會導致集群不可用。

11. ES是靜態分片,一旦分片數在創建索引時確定那麼後繼不能修改。

12. ES里提供了type,很多人以為type是物理表,一個type的數據是獨立存儲的;但是在ES內部並不是這樣,type在ES內部僅僅是一個字段。所以在很多數據能分為獨立index的情況下,不要放到一個index里用type去分。只有嵌套類和父子類的情況下使用type才是合理的。

13. ES並不提供原生的中文分詞的能力。有第三方的中文分詞的插件,比如ik等。Ik是個toy分詞器,有嚴肅的分詞需求的話,請在使用ES之前使用獨立的分詞器分好詞後向ES寫入。

14. ES中的index,首先會進行分片,每一個分片數據一般都會有自己的副本數據,ES分配分片的策略會保證同一個分片數據和自己的副本不會分配到同一個節點上。當集群中的某一節點宕機後,ES的master在ping該節點時通過一定的策略會發現該節點不存活;會開啟ES的恢復過程

15. ES沒有update的能力。所有的update都是標記刪除老文檔,然後重新insert一條新文檔。

java中如何直接讀取es語言

Elasticsearch不是java語言開發的,所以必須要通過api才能調用。你可以看看有沒有第三方包可以直接操作。

es查詢數據的工作原理是什麼?

查詢,GET某一條數據,寫入了某個document,這個document會自動給你分配一個全局唯一的id,doc id,同時也是根據doc id進行hash路由到對應的primary shard上面去。也可以手動指定doc id,比如用訂單id,用戶id。

我們可以通過doc id來查詢,會根據doc id進行hash,判斷出來當時把doc id分配到了哪個shard上面去,從那個shard去查詢

1)客戶端發送請求到任意一個node,成為coordinate node(協調結點)

2)coordinate node進行hash後對document進行路由,將請求轉發到對應的node,此時會使用round-robin 隨機輪詢算法 ,在primary shard以及其所有replica node中 隨機選擇一個 ,讓讀請求負載均衡

3)接收請求的node返回document給coordinate node

4)coordinate node返回document給客戶端

es最強大的是做全文檢索,就是比如你有三條數據

java真好玩兒啊

java好難學啊

j2ee特別牛

你根據java關鍵詞來搜索,將包含java的document給搜索出來

es就會給你返回:java真好玩兒啊,java好難學啊

1)客戶端發送請求到一個coordinate node

2)協調節點 將搜索請求轉發到 所有的shard 對應的primary shard或replica shard

3)query phase: 每個shard將自己的搜索結果 (其實就是一些 doc id ), 返回給協調節點 ,由協調節點進行數據的 合併、排序、分頁 等操作,產出最終結果

4)fetch phase:接着由 協調節點,根據doc id去各個節點上拉取實際的document數據 ,最終返回給客戶端

尤其要注意的這裡是先拿的id喲

ES 常見面試問題

1 增大內存: es性能優化的殺手鐧: filesystem cache(OS cache): 也就是說 盡量讓內存可以容納所有的索引數據文件,那麼搜索的時候就基本都是走內存的,性能會非常高。磁盤和OS cache掃描速度相差近一個數量級,可能一個是1到幾百毫秒,另一個是秒。最佳的情況下,就是單機機器的內存,至少可以容納單機數據量的一半。另一個方面就是寫數據的時候,僅僅寫入要用來檢索的少數幾個字段就可以了,其餘的數據放到hbase或者mysql上

2 數據預熱

假設機器內存達到上面的要求,比如 內存是100G,數據是200G。那麼有一半的數據存放在磁盤上,那麼這個時候可以設計一個 數據預熱子系統, 就是對熱數據每隔一段時間,就提前訪問一下,讓熱數據進入 filesystem cache 裏面去。這樣下次別人訪問的時候,性能一定會好很多。

3 document 模型設計

document 模型設計是非常重要的,很多操作,不要在搜索的時候才想去執行各種複雜的亂七八糟的操作,盡量存放單純的數據放到ES上去,不要考慮用 es 做一些它不好操作的事情,比如 join/nested/parent-child 搜索都要盡量避免,性能都很差的。

4 分頁性能優化

分頁性能差的原因:

解決方案1:跟產品經理說,你系統不允許翻那麼深的頁,默認翻的越深,性能就越差。

解決方案2:類似於 app 里的推薦商品不斷下拉出來一頁一頁的

就像淘寶商品一樣,一頁一頁往下刷,不能從第一頁跳到100頁,從100頁跳到50頁,不能這樣操作。

可以使用 scroll api 來實現,scroll 會一次性給你生成所有數據的一個快照,然後每次滑動向後翻頁就是通過游標 scroll_id 移動,獲取下一頁下一頁這樣子,性能會比上面說的那種分頁性能要高很多很多,基本上都是毫秒級的。

初始化時必須指定 scroll 參數,告訴 es 要保存此次搜索的上下文多長時間。你需要確保用戶不會持續不斷翻頁翻幾個小時,否則可能因為超時而失敗。

除了用 scroll api,你也可以用 search_after 來做,search_after 的思想是使用前一頁的結果來幫助檢索下一頁的數據,顯然,這種方式也不允許你隨意翻頁,你只能一頁頁往後翻。初始化時,需要使用一個唯一值的字段作為 sort 字段。參考:

先寫入內存 buffer,在 buffer 里的時候數據是搜索不到的;同時將數據寫入 translog 日誌文件。

如果 buffer 快滿了,或者到一定時間,就會將內存 buffer 數據 refresh 到一個新的 segment file 中,但是此時數據不是直接進入 segment file 磁盤文件,而是先進入 os cache 。這個過程就是 refresh。只要數據進入了OS cache那麼就可以被訪問到了。

每隔 1 秒鐘,es 將 buffer 中的數據寫入一個新的 segment file (如果 buffer 裏面此時沒有數據,那當然不會執行 refresh 操作) ,每秒鐘會產生一個新的磁盤文件 segment file,這個 segment file 中就存儲最近 1 秒內 buffer 中寫入的數據。

這裡就解釋了為什麼叫 es 是 准實時 的? NRT,全稱 near real-time。默認是每隔 1 秒 refresh 一次的,所以 es 是准實時的,因為寫入的數據 1 秒之後才能被看到。可以通過 es 的 restful api 或者 java api,手動執行一次 refresh 操作,就是手動將 buffer 中的數據刷入 os cache中(但是這樣會影響ES批量插入數據的效率),讓數據立馬就可以被搜索到。只要數據被輸入 os cache 中,buffer 就會被清空了,因為不需要保留 buffer 了,數據在 translog 裏面已經持久化到磁盤去一份了。

重複上面的步驟,新的數據不斷進入 buffer 和 translog,不斷將 buffer 數據寫入一個又一個新的 segment file 中去,每次 refresh 完 buffer 清空,translog 保留。隨着這個過程推進,translog 會變得越來越大。當 translog 達到一定長度的時候,就會觸發 commit 操作。

commit 操作發生第一步,就是將 buffer 中現有數據 refresh 到 os cache 中去,清空 buffer。然後,將一個 commit point 寫入磁盤文件,裏面標識着這個 commit point 對應的所有 segment file,同時強行將 os cache 中目前所有的數據都 fsync 到磁盤文件中去。最後清空 現有 translog 日誌文件,重啟一個 translog,此時 commit 操作完成。

這個 commit 操作叫做 flush。默認 30 分鐘自動執行一次 flush,但如果 translog 過大,也會觸發 flush。flush 操作就對應着 commit 的全過程,我們可以通過 es api,手動執行 flush 操作,手動將 os cache 中的數據 fsync 強刷到磁盤上去。

translog 日誌文件的作用是什麼?你執行 commit 操作之前,數據要麼是停留在 buffer 中,要麼是停留在 os cache 中,無論是 buffer 還是 os cache 都是內存,一旦這台機器死了,內存中的數據就全丟了。所以需要將數據對應的操作寫入一個專門的日誌文件 translog 中,一旦此時機器宕機,再次重啟的時候,es 會自動讀取 translog 日誌文件中的數據,恢復到內存 buffer 和 os cache 中去 這裡和Redis持久化機制是類似的 。

translog 其實也是先寫入 os cache 的,默認每隔 5 秒刷一次到磁盤中去,所以默認情況下,可能有 5 秒的數據會僅僅停留在 buffer 或者 translog 文件的 os cache 中,如果此時機器掛了,會丟失 5 秒鐘的數據。但是這樣性能比較好,最多丟 5 秒的數據。也可以將 translog 設置成每次寫操作必須是直接 fsync 到磁盤,但是性能會差很多。

總結一下,數據先寫入內存 buffer,然後每隔 1s,將數據 refresh 到 os cache,到了 os cache 數據就能被搜索到(所以我們才說 es 從寫入到能被搜索到,中間有 1s 的延遲)。每隔 5s,將數據寫入 translog 文件(磁盤裏面)(這樣如果機器宕機,內存數據全沒,最多會有 5s 的數據丟失),translog 大到一定程度,或者默認每隔 30mins,會觸發 commit 操作,將緩衝區的數據都 flush 到 segment file 磁盤文件中。

可以通過 doc id 來查詢,會根據 doc id 進行 hash,判斷出來當時把 doc id 分配到了哪個 shard 上面去,從那個 shard 去查詢。

客戶端發送請求到任意一個 node,成為 coordinate node。

coordinate node 對 doc id 進行哈希路由,將請求轉發到對應的 node,此時會使用 round-robin 隨機輪詢算法,在 primary shard 以及其所有 replica 中隨機選擇一個,讓讀請求負載均衡。

接收請求的 node 返回 document 給 coordinate node。

coordinate node 返回 document 給客戶端。

搜索

es 最強大的是做全文檢索,就是比如你有三條數據:

java真好玩兒啊

java好難學啊

j2ee特別牛

你根據 java 關鍵詞來搜索,將包含 java的 document 給搜索出來。es 就會給你返回:java真好玩兒啊,java好難學啊。

1 客戶端發送請求到一個 coordinate node。

2 協調節點將搜索請求轉發到所有的 shard 對應的 primary shard 或 replica shard,都可以。

3 query phase:每個 shard 將自己的搜索結果(其實就是一些 doc id)返回給協調節點,由協調節點進行數據的合併、排序、分頁等操作,產出最終結果。

4 fetch phase:接着由協調節點根據 doc id 去各個節點上拉取實際的 document 數據,最終返回給客戶端。

如果是更新操作,就是將原來的 doc 標識為 deleted 狀態,然後新寫入一條數據。

buffer 每 refresh 一次,就會產生一個 segment file,所以默認情況下是 1 秒鐘一個 segment file,這樣下來 segment file 會越來越多,此時會定期執行 merge。每次 merge 的時候,會將多個 segment file 合併成一個 (這裡類似於Redis的RDB文件重寫) ,同時這裡會將標識為 deleted 的 doc 給 物理刪除掉 ,然後將新的 segment file 寫入磁盤,這裡會寫一個 commit point,標識所有新的 segment file,然後打開 segment file 供搜索使用,同時刪除舊的 segment file。

如何在Spring中注入ElasticSearch實例

企業級項目開發中,大多數公司都會集成Spring來簡化開發成本,要使用Spring自然少不了一大堆需要依賴注入的Bean,通常情況下,我們會選擇

在spring的xml中,配置一些類的實例,比如連接池,或者配置文件初始化類,或者集成duboo時配置一些Service的引用等等。

些類的實例生成比較複雜,直接在xml中,是沒法進行配置的,比如我想在Spring注入ElasticSearch的Client實例,注意(這裡並不

是使用的spring-data-elasticsearch項目),而是使用原始的ElasticSearch的API。

我們先看下,在非Spring的項目中,如何初始化ElasticSearch的Client實例:

Java代碼

//es的客戶端實例

static Client client=null;

static {

//設置集群名字

Settings settings = ImmutableSettings.settingsBuilder()

.put(“cluster.name”, “search”)

.put(“client.transport.sniff”, true)

. build();

//連接單台機器,注意ip和端口號,不能寫錯

client=new TransportClient(settings)

.addTransportAddress(new InetSocketTransportAddress(“192.168.1.187”, 9300))

.addTransportAddress(new InetSocketTransportAddress(“192.168.1.121”, 9300))

.addTransportAddress(new InetSocketTransportAddress(“192.168.1.122”, 9300));

}

於ElasticSearch的Client實例是通過各種組裝加工而成,並沒法直接在Spring的xml中使用Bean標籤進行初始化,這時候我們可

以使用@Configuration註解,來在Java類中,生成bean實例,這個註解和使用spring的xml進行注入功能大致相同,只不過能直接

在Java類生成一個類實例,比較靈活而已。最終的代碼如下:

Java代碼

package cn.bizbook.product.elk.config;

import org.elasticsearch.client.Client;

import org.elasticsearch.client.transport.TransportClient;

import org.elasticsearch.common.settings.ImmutableSettings;

import org.elasticsearch.common.settings.Settings;

import org.elasticsearch.common.transport.InetSocketTransportAddress;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

/**

* Created by qindongliang on 2016/4/6.

*/

@Configuration

public class FactoryBean {

//配置文件工具類

@Autowired

private ESConf esConf;

//注入的ElasticSearch實例

@Bean(name = “client”)

public Client getESClient(){

//設置集群名字

Settings settings = ImmutableSettings.settingsBuilder()

.put(“cluster.name”, esConf.getClusterName())

.build();

Client client=new TransportClient(settings);

//讀取的ip列表是以逗號分隔的

for(String ip:esConf.getIps().split(“,”)){

((TransportClient)client).addTransportAddress(new InetSocketTransportAddress(ip,esConf.getPort()));

}

return client;

}

}

最後來看下,如何在DAO層,引用client實例,非常easy:

Java代碼

@Resource(name = “client”)

private Client client;

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/206262.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-07 17:50
下一篇 2024-12-07 17:50

相關推薦

  • Java JsonPath 效率優化指南

    本篇文章將深入探討Java JsonPath的效率問題,並提供一些優化方案。 一、JsonPath 簡介 JsonPath是一個可用於從JSON數據中獲取信息的庫。它提供了一種DS…

    編程 2025-04-29
  • Python周杰倫代碼用法介紹

    本文將從多個方面對Python周杰倫代碼進行詳細的闡述。 一、代碼介紹 from urllib.request import urlopen from bs4 import Bea…

    編程 2025-04-29
  • java client.getacsresponse 編譯報錯解決方法

    java client.getacsresponse 編譯報錯是Java編程過程中常見的錯誤,常見的原因是代碼的語法錯誤、類庫依賴問題和編譯環境的配置問題。下面將從多個方面進行分析…

    編程 2025-04-29
  • Java Bean加載過程

    Java Bean加載過程涉及到類加載器、反射機制和Java虛擬機的執行過程。在本文中,將從這三個方面詳細闡述Java Bean加載的過程。 一、類加載器 類加載器是Java虛擬機…

    編程 2025-04-29
  • Python字符串寬度不限制怎麼打代碼

    本文將為大家詳細介紹Python字符串寬度不限制時如何打代碼的幾個方面。 一、保持代碼風格的統一 在Python字符串寬度不限制的情況下,我們可以寫出很長很長的一行代碼。但是,為了…

    編程 2025-04-29
  • Java騰訊雲音視頻對接

    本文旨在從多個方面詳細闡述Java騰訊雲音視頻對接,提供完整的代碼示例。 一、騰訊雲音視頻介紹 騰訊雲音視頻服務(Cloud Tencent Real-Time Communica…

    編程 2025-04-29
  • Java Milvus SearchParam withoutFields用法介紹

    本文將詳細介紹Java Milvus SearchParam withoutFields的相關知識和用法。 一、什麼是Java Milvus SearchParam without…

    編程 2025-04-29
  • Python基礎代碼用法介紹

    本文將從多個方面對Python基礎代碼進行解析和詳細闡述,力求讓讀者深刻理解Python基礎代碼。通過本文的學習,相信大家對Python的學習和應用會更加輕鬆和高效。 一、變量和數…

    編程 2025-04-29
  • Java 8中某一周的周一

    Java 8是Java語言中的一個版本,於2014年3月18日發佈。本文將從多個方面對Java 8中某一周的周一進行詳細的闡述。 一、數組處理 Java 8新特性之一是Stream…

    編程 2025-04-29
  • Java判斷字符串是否存在多個

    本文將從以下幾個方面詳細闡述如何使用Java判斷一個字符串中是否存在多個指定字符: 一、字符串遍歷 字符串是Java編程中非常重要的一種數據類型。要判斷字符串中是否存在多個指定字符…

    編程 2025-04-29

發表回復

登錄後才能評論