Elasticsearch詳解-續

Elasticsearch詳解-續

96 
Chandler_珏瑜 22d8d123 271c 4d80 9c59 6990844a9e37 
 7.6 2019.05.22 10:46* 字數 8366 閱讀 675評論 4

5.3 性能調優

 Elasticsearch的默認配置,是綜合了數據可靠性、寫入速度、搜索實時性等因素。實際使用時,咱們須要根據公司要求,進行偏向性的優化。javascript

5.3.1 寫優化

 假設咱們的應用場景要求是,每秒300萬的寫入速度,每條500字節左右。
 正對這種對於搜索性能要求不高,可是對寫入要求較高的場景,咱們須要儘量的選擇恰當寫優化策略。綜合來講,能夠考慮如下幾種方面來提高寫索引的性能:css

  • 加大 translog flush ,目的是下降 iops、writeblock
  • 增長index refresh間隔,目的是減小segment merge 的次數
  • 調整bulk線程池和隊列
  • 優化節點間的任務分佈
  • 優化lucenue層的索引創建,目的是下降CPU及IO
1. 批量提交

 Elasticsearch提供了bulk API支持批量操做,當咱們有大量的寫任務時,可使用bulk來進行批量寫入。每次提交的數據量爲多少時,能達到最優的性能,主要受到文件大小、網絡狀況、數據類型、集羣狀態等因素影響。
 通用的策略以下:java

bulk默認設置批量提交的數據量不能超過100M。數據條數通常是根據文檔的大小和服務器性能而定的,可是單次批處理的數據大小應從5MB~15MB逐漸增長,當性能沒有提高時,把這個數據量做爲最大值。node

 咱們能夠跟着,感覺一下bulk接口,以下所示:linux

$ vi request
$ cat request
{ "index" : { "_index" : "chandler","_type": "test", "_id" : "1" } } { "name" : "錢丁君","age": "18" } $ curl -s -H "Content-Type: application/json" -XPOST localhost:9200/_bulk --data-binary @request; echo {"took":214,"errors":false,"items":[{"index":{"_index":"chandler","_type":"test","_id":"1","_version":1,"result":"created","_shards":{"total":2,"successful":1,"failed":0},"_seq_no":0,"_primary_term":1,"status":201}}]} $ curl -XGET localhost:9200/chandler/test/1?pretty { "_index" : "chandler", "_type" : "test", "_id" : "1", "_version" : 1, "found" : true, "_source" : { "name" : "錢丁君", "age" : "18" } } 

 bulk不支持get操做,由於沒什麼用處。web

2. 優化存儲設備

 Elasticsearch是一種密集使用磁盤的應用,在段合併的時候會頻繁操做磁盤,因此磁盤要求較高,當磁盤速度提高以後,集羣的總體性能會大幅度提升。
 磁盤的選擇,提供如下幾點建議:數據庫

  1. 使用固態硬盤(Solid State Disk)替代機械硬盤。SSD與機械磁盤相比,具備高效的讀寫速度和穩定性。
  2. 使用RAID 0。RAID0條帶化存儲,能夠提高磁盤讀寫效率。
  3. 在Elasticsearch的服務器上掛載多塊硬盤。使用多塊硬盤同時進行讀寫操做提高效率,在配置文件elasticsearch中設置多個存儲路徑,以下所示:
path.data:/path/to/data1,/path/to/data2。 
  1. 避免使用NFS(Network File System)等遠程存儲設備,網絡 的延遲對性能的影響是很大的。
3. 合理使用合併

 Lucene以段的形式存儲數據。當有新的數據寫入索引時,Lucene就會自動建立一個新的段。隨着數據量的變化,段的數量會愈來愈多,消耗的多文件句柄數及CPU就越多,查詢效率就會降低。
 因爲Lucene段合併的計算量龐大,會消耗大量的I/O,因此Elasticsearch默認採用較保守的策略,讓後臺按期進行段合併,以下所述:json

  • 索引寫入效率降低:當段合併的速度落後於索引寫入的速度時,Elasticsearch會把索引的線程數量減小到1。這樣能夠避免出現堆積的段數量爆發,同時在日誌中打印出「now throttling indexing」INFO級別的「警告」信息。
  • 提高段合併速度:Elasticsearch默認對段合併的速度是20m/s,若是使用了SSD,咱們能夠經過如下的命令將這個合併的速度增長到100m/s:
PUT /_cluster/settings
{
    "persistent" : { "indices.store.throttle.max_bytes_per_sec" : "100mb" } } 
4. 減小refresh的次數

 Lucene在新增數據時,採用了延遲寫入的策略,默認狀況下索引的refresh_interval爲1秒。Lucene將待寫入的數據先寫到內存中,超過1秒(默認)時就會觸發一次refresh,而後refresh會把內存中的的數據刷新到操做系統的文件緩存系統中。若是咱們對搜索的實效性要求不高,能夠將refresh週期延長,例如30秒。這樣還能夠有效地減小段刷新次數,但這同時意味着須要消耗更多的Heap內存。以下所示:bootstrap

index.refresh_interval:30s 
5. 加大flush設置

 flush的主要目的是把文件緩存系統中的段持久化到硬盤,當Translog的數據量達到512MB或者30分鐘時,會觸發一次Flush。 index.translog.flush_threshold_size 參數的默認值是512MB,咱們進行修改。
 增長參數值意味着文件緩存系統中可能須要存儲更多的數據,因此咱們須要爲操做系統的文件緩存系統留下足夠的空間。vim

6. 減小副本的數量

 Elasticsearch爲了保證集羣的可用性,提供了replicas(副本)支持,然而每一個副本也會執行分析、索引及可能的合併過程,因此replicas的數量會嚴重影響寫索引的效率。當寫索引時,須要把寫入的數據都同步到副本節點,副本節點越多,寫索引的效率就越慢。
 若是咱們須要大批量進行寫入操做,能夠先禁止replica複製,設置index.number_of_replicas: 0 關閉副本。在寫入完成後,replica修改回正常的狀態。

5.3.2 讀優化

1. 避免大結果集和深翻

 在5.2.5節中介紹了集羣中的查詢流程,若是想要查詢從from開始的size條數據,須要每一個分片查詢打分排名在前面的from+size條數據。協同節點將收集到的n✖️(from+size)條數據聚合,再進行一次排序,而後從from+size開始返回size條數據。
 當from、size或者n中有一個值很大的時候,須要參加排序的數量也會增加,這樣的查詢會消耗不少CPU資源,從而致使效率的下降。
 爲了提高查詢效率,Elasticsearch提供了scroll和scroll-scan這兩種查詢模式。

1)scroll

 scroll是爲檢索大量的結果而設計的。例如,咱們須要查詢1~100頁的數據,每頁100條數據。
 若是使用search查詢:每次都須要在每一個分片上查詢得分最高的from+100條數據,而後協同節點把收集到的n✖️(from+100)條數據聚合起來再進行一次排序。每次返回from+1開始的100條數據,而且要重複執行100次。
 若是使用scroll查詢:在各個分片上查詢10000條數據,協同節點聚合n✖️10000條數據進行合併、排序,並將排名前10000的結果快照起來。這樣作的好處是減小了查詢和排序的次數。
 Scroll初始查詢的命令是:

$ vim scroll
$ cat scroll
{
    "query": { "match": { "name": "錢丁君" } }, "size":20 } $ curl -s -H "Content-Type: application/json; charset=UTF-8" -XGET localhost:9200/chandler/test/_search?scroll=2m --data-binary @scroll; echo {"_scroll_id":"DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAAAGFlB6Y3QtNk9oUmdpc09Tb21rX2NXQXcAAAAAAAAABxZQemN0LTZPaFJnaXNPU29ta19jV0F3AAAAAAAAAAgWUHpjdC02T2hSZ2lzT1NvbWtfY1dBdwAAAAAAAAAJFlB6Y3QtNk9oUmdpc09Tb21rX2NXQXcAAAAAAAAAChZQemN0LTZPaFJnaXNPU29ta19jV0F3","took":14,"timed_out":false,"_shards":{"total":5,"successful":5,"skipped":0,"failed":0},"hits":{"total":1,"max_score":0.8630463,"hits":[{"_index":"chandler","_type":"test","_id":"1","_score":0.8630463,"_source":{ "name" : "錢丁君","age": "18" }}]}} 

 以上查詢語句的含義是,在chandler索引的test type裏查詢字段name包含「錢丁君」的數據。scroll=2m表示下次請求的時間不能超過2分鐘,size表示此次和後續的每次請求一次返回的數據條數。在此次查詢的結果中除了返回了查詢到的結果,還返回了一個scroll_id,能夠把它做爲下次請求的參數。
 再次請求的命令,以下所示:

 
scroll查詢.png

 由於此次並無到分片裏查詢數據,而是直接在生成的快照裏面以遊標的形式獲取數據,因此此次查詢並無包含index和type,也沒有查詢條件。

 

  • "scroll": "2m":指本次請求的時間不能超過2分鐘。
  • scroll_id:是上次查詢時返回的scroll_id。
2)scroll-scan

 Scroll是先作一次初始化搜索把全部符合搜索條件的結果緩存起來生成一個快照,而後持續地、批量地從快照里拉取數據直到沒有數據剩下。而這時對索引數據的插入、刪除、更新都不會影響遍歷結果,所以scroll 並不適合用來作實時搜索。其思路和使用方式與scroll很是類似,可是scroll-scan關閉了scroll中最耗時的文本類似度計算和排序,使得性能更加高效。
 爲了使用scroll-scan,須要執行一個初始化搜索請求,將search_type設置成scan,告訴Elasticsearch集羣不須要文本類似計算和排序,只是按照數據在索引中順序返回結果集:

$ vi scroll
$ cat scroll
{
    "query": { "match": { "name": "錢丁君" } }, "size":20, "sort": [ "_doc" ] } $ curl -H "Content-Type: application/json; charset=UTF-8" -XGET 'localhost:9200/chandler/test/_search?scroll=2m&pretty=true' --data-binary @scroll { "_scroll_id" : "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAABWFlB6Y3QtNk9oUmdpc09Tb21rX2NXQXcAAAAAAAAAVxZQemN0LTZPaFJnaXNPU29ta19jV0F3AAAAAAAAAFgWUHpjdC02T2hSZ2lzT1NvbWtfY1dBdwAAAAAAAABZFlB6Y3QtNk9oUmdpc09Tb21rX2NXQXcAAAAAAAAAWhZQemN0LTZPaFJnaXNPU29ta19jV0F3", "took" : 3, "timed_out" : false, "_shards" : { "total" : 5, "successful" : 5, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : 1, "max_score" : null, "hits" : [ { "_index" : "chandler", "_type" : "test", "_id" : "1", "_score" : null, "_source" : { "name" : "錢丁君", "age" : "18" }, "sort" : [ 0 ] } ] } } 

注意:Elasticsearch 2.1.0版本以後移除了search_type=scan,使用"sort": [ "_doc"]進行代替。

 scroll和scroll-scan有一些差異,以下所示:

  1. scroll-scan不進行文本類似度計算,不排序,按照索引中的數據順序返回
  2. scroll-scan不支持聚合操做。
  3. scroll-scan的參數size表明着每一個分片上的請求的結果數量,每次返回n✖️size條數據。而scroll每次返回size條數據。
2. 選擇合適的路由

 ES中所謂的路由和IP網絡不一樣,是一個相似於Tag的東西。在建立文檔的時候,能夠經過字段爲文檔增長一個路由屬性的Tag。在多分片的Elasticsearch集羣中,對搜索的查詢大體分爲以下兩種。

 (1)ES內在機制決定了擁有相同路由屬性的文檔,必定會被分配到同一個分片上,不管是主分片仍是副本。查詢時能夠根據routing信息,直接定位到目標分片,避免查詢全部的分片,再通過協調節點二次排序。若是5-24所示。


 
圖 5-24

 (2)若是在查詢條件中不包含routing,在查詢時就遍歷全部分片,整個查詢主要分爲Scatter、Sather兩個過程。

  • Scatter(分發):請求到達協調節點以後,協調節點將查詢請求分發給每一個分片。
  • Gather(聚合):協調點在每一個分片上完成搜索,再將搜索到的結果集進行排序,將結果數據返回給用戶。如圖5-25所示:
     
    圖 5-25

     經過對比上述兩種查詢流程,咱們不難發現,使用routing信息查找的效率很高,避免了多餘的查詢。因此咱們在設計Elasticsearch mapping時要合理地利用routing信息,來提高查詢的效率。例如,在大型的本地分類網站中,能夠將城市id做爲routing的條件,讓同一個城市的數據落在相同的分片中。默認的公司以下:
shard = hash(routing)%number_of_primary_shards 

 不過須要注意的是,根據城市id進行分片時,也會容易出現分片不均勻的狀況。例如,大型城市的數據過多,而小城市的數據太少,致使分片之間的數據量差別很大。這時就能夠進行必要的調整,好比把多個小城市的數據合併到一個分片上,把大城市的數據按區域進行拆分到不一樣分配。

3. SearchType

 在Scatter、Gather的過程當中,節點間的數據傳輸和打分(SearchType),能夠根據不一樣的場景選擇。以下所示

  1. QUERY_THEN_FETCH:Elasticsearch默認的搜索方式。第一步,先向全部的分片發請求,各分片只返回文檔的類似度得分和文檔的id,而後協調節點按照各分片返回的分數進行從新排序和排名,再取出須要返回給客戶端的size個文檔id;第2步,在相關的分片中取出文檔的詳細信息並返回給用戶。
  2. QUERY_AND_FETCH:協調節點向全部分片發送查詢請求,各分片將文檔的類似度得分和文檔的詳細信息一塊兒返回。而後,協調節點進行從新排序,再取出須要返回給客戶端的數據,將其返回給客戶端。因爲只須要在分片中查詢一次,因此性能是最好的。
  3. DFS_QUERY_THEN_FETCH:與QUERY_THEN_FETCH相似,但它包含一個額外的階段:在初始查詢中執行全局的詞頻計算,以使得更精確地打分,從而讓查詢結果更相關。QUERY_THEN_FETCH使用的是分片內部的詞頻信息,而DFS_QUERY_THEN_FETCH使用訪問公共的詞頻信息,因此相比QUERY_THEN_FETCH性能更低。
  4. DFS_QUERY_AND_FETCH:與QUERY_AND_FETCH相似,不過使用的是全局的詞頻。
4. 按期刪除

 因爲在Lucene中段具備不變性,每次進行刪除操做後不會當即從硬盤中進行實際的刪除,而是產生一個.del文件記錄刪除動做。隨着刪除操做的增加,.del文件會越來也多。當咱們進行查詢操做的時候,被刪除的數據還會參與檢索中,而後根據.del文件進行過濾。.del文件越多,查詢過濾過程越長,進而影響查詢的效率。當機器空閒時,咱們能夠經過以下命令刪除文件,來提高查詢的效率:

$ curl -XPOST localhost:9200/chandler/_forcemerge?only_expunge_deletes=true {"_shards":{"total":10,"successful":5,"failed":0}} 

按期對再也不更新的索引作optimize (ES2.0之後更改成force merge api)。這Optimze的實質是對segment file強制作合併,能夠節省大量的segment memory。

5.4.3 堆大小的設置

 Elasticsearch默認安裝後設置的內存是1GB,對於任何一個現實業務來講,這個設置都過小了。若是是經過解壓安裝的Elasticsearch,則在Elasticsearch安裝文件中包含一個jvm.option文件,添加以下命令來設置Elasticsearch的堆大小:

-Xms10g
-Xmx10g

 Xms表示堆的初始大小,Xmx表示可分配的最大內存,都是10GB。確保Xmx和Xms的大小是相同的,其目的是爲了可以在java垃圾回收機制清理完堆區後不須要從新分隔計算堆區的大小而浪費資源,能夠減輕伸縮堆大小帶來的壓力。
 也能夠經過設置環境變量的方式設置堆的大小。服務進程在啓動時候會讀取這個變量,並相應的設置堆的大小。好比:

export ES_HEAP_SIEZE=10g 

 也能夠經過命令行參數的形式,在程序啓動的時候把內存大小傳遞給Elasticsearch,以下所示:

./bin/elasticsearch -Xmx10g -Xms10g

這種設置方式是一次性的,在每次啓動Elasticsearch時都須要添加。

 假設你有一個64G內存的機器,按照正常思惟思考,你可能會認爲把64G內存都給Elasticsearch比較好,但現實是這樣嗎, 越大越好?雖然內存對Elasticsearch來講是很是重要的,可是答案是否認的!由於Elasticsearch堆內存的分配須要知足如下兩個原則:

  • 不要超過物理內存的50%:Lucene的設計目的是把底層OS裏的數據緩存到內存中。Lucene的段是分別存儲到單個文件中的,這些文件都是不會變化的,因此很利於緩存,同時操做系統也會把這些段文件緩存起來,以便更快的訪問。若是咱們設置的堆內存過大,Lucene可用的內存將會減小,就會嚴重影響下降Lucene的全文本查詢性能。
  • 堆內存的大小最好不要超過32GB:在Java中,全部對象都分配在堆上,而後有一個Klass Pointer指針指向它的類元數據。這個指針在64位的操做系統上爲64位,64位的操做系統可使用更多的內存(264)。在32位的系統上爲32位,32位的操做系統的最大尋址空間爲4GB(232)。可是64位的指針意味着更大的浪費,由於你的指針自己大了。浪費內存不算,更糟糕的是,更大的指針在主內存和緩存器(例如LLC, L1等)之間移動數據的時候,會佔用更多的帶寬。

 Java使用內存指針壓縮(Compressed Oops)技術來解決這個問題。它的指針再也不表示對象在內存中的精確位置,而是表示偏移量。這意味着32位的指針能夠引用4GB個Byte,而不是4GB個bit。也就是說,當堆內存爲32GB的物理內存時,也能夠用32位的指針表示。
 不過,在越過那個神奇的邊界----32GB時,指針就會變爲普通對象的指針,每一個對象的指針都變長了,就會浪費更多的內存,下降了CPU的性能,還要讓GC應對更大的內存。事實上,當內存到達40~40GB時,有效的內存才至關於內存對象指針壓縮技術時的32GB內存。因此即使你有足夠的內存,也儘可能不要超過32G,好比咱們能夠設置爲31GB:

-Xms31g
-Xmx31g

  32GB是ES一個內存設置限制,那若是你的機器有很大的內存怎麼辦呢?如今的機器內存廣泛增加,甚至能夠看到有300-500GB內存的機器。這時咱們須要根據業務場景,進行恰當內存的分配。

  • 業務場景是以全文檢索爲主:依然能夠給Elasticsearch分配小於32GB的堆內存,剩下的交給Lucene用做操做系統的文件系統緩存,全部的segment都緩存起來,會加快全文檢索。
  • 業務場景中有不少的排序和聚合:咱們能夠考慮一臺機器上建立兩個或者更多ES節點,而不要部署一個使用32+GB內存的節點。仍然要 堅持50%原則,假設 你有個機器有128G內存,你能夠建立兩個node,使用32G內存。也就是說64G內存給ES的堆內存,剩下的64G給Lucene。

5.3.4 服務器配置的選擇

swapping是性能的墳墓

 在選擇Elasticsearch服務器時,要儘量地選擇與當前應用場景相匹配的服務器。若是服務器配置很低,則意味着須要更多的節點,節點數量的增長會致使集羣管理的成本大幅度提升。若是服務器配置很高,,而在單機上運行多個節點時,也會增長邏輯的複雜度。
 在計算機中運行的程序均需在內存執行,若內存消耗殆盡將致使程序沒法進行。爲了解決這個問題,操做系統使用一種叫做虛擬內存的技術。當內存耗盡時,操做系統就會自動把內存中暫時不使用的數據交換到硬盤中,須要使用的時候再從硬盤交換到內存。
 若是內存交換到磁盤上須要10毫秒,從磁盤交換到內存須要20浩渺,那麼多的操做時延累加起來,將致使幾何級增加。不難看出swapping對於性能是多麼可怕。因此爲了使Elasticsearch有更好等性能,強烈建議關閉swap。
 關閉swap的方式以下。
 (1)暫時禁用。若是咱們想要在linux服務器上暫時關閉,能夠執行以下命令,但在服務器重啓後失效:

sudo swapoff -a

 (2)永久性關閉。咱們能夠修改/etc/sysctl.conf(不一樣等操做系統路徑有可能不一樣),增長以下參數:

vm.swappiness = 1 //0-100,則表示越傾向於使用虛擬內存。 

注意:swappiness設置爲1比設置爲0要好,由於在一些內核版本,swappness=0會引起OOM(內存溢出)。

  swappiness默認值爲60,當設置爲0時,在某些操做系統中有可能會觸發系統級的OOM-killer,例如在Linux內核的內存不足時,爲了防止系統的崩潰,會自動強制kill一個「bad」進程。
 (3)在Elasticsearch中設置。若是上面的方法都不能作到,你須要打開配置文件中的mlockall開關,它的做用就是運行JVM鎖住內存,禁止OS交換出去。在elasticsearch.yml配置以下:

bootstrap.mlockall: true 

5.3.5 硬盤的選擇和設置

 因此,若是條件容許,則請儘量地使用SSD,它的讀寫性能將遠遠超出任何旋轉介質的硬盤(如機械硬盤、磁帶等)。基於SSD的Elasticsarch集羣節點對於查詢和索引性能都有提高。
 另外不管是使用固態硬盤仍是使用機械硬盤,咱們都建議將磁盤的陣列模式設置爲RAID 0,以此來提高磁盤的寫性能。

5.4.6 接入方式

 Elastic search提供了Transport Client(傳輸客戶端)和Node Client(節點客戶端)的接入方式,這兩種方式各有利弊,分別對應不一樣的應用場景。

1. Transport Client

 Transport Client做爲一個集羣和應用程序之間的通訊層,和集羣是安全解耦的。因爲與集羣解耦,因此在鏈接集羣和銷燬鏈接時更加高效,適合大量的客戶端鏈接。

2. Node Client

 Node Client把應用程序看成一個集羣中的Client節點(非Data和Master節點)。因爲它是集羣一個的內部節點,意味着它能夠感知整個集羣的狀態、全部節點的分佈狀況、分片的分佈情況等。
 因爲Node Client是集羣的一部分,因此在接入和退出集羣時進行比較複雜操做,而且還會影響整個集羣的狀態,因此Node Client更適合少許客戶端,可以提供更好的執行效率。

5.4.7 角色隔離和腦裂

1. 角色隔離

 Elasticsearch集羣中的數據節點負責對數據進行增、刪、改、查和聚合等操做,因此對CPU、內存和I/O的消耗很大。在搭建Elasticsearch集羣時,咱們應該對Elasticsearch集羣中的節點進行角色劃分和隔離。
 候選主節點:

node.master=true node.data=false 

 數據節點:

node.master=false node.data=true 

 最後造成如圖5-26所示的邏輯劃分。


 
圖 5-26 elasticsearch集羣
2. 避免腦裂

 網絡異常可能會致使集羣中節點劃分出多個區域,區域發現沒有master節點的時候,會選舉出了本身區域內Maste節點r,致使一個集羣被分裂爲多個集羣,使集羣之間的數據沒法同步,咱們稱這種現象爲腦裂。爲了防止腦裂,咱們須要在Master節點的配置文件中添加以下參數:

discovery.zen.minimum_master_nodes=(master_eligible_nodes/2)+1 //默認值爲1 

 其中master_eligible_nodes爲Master集羣中的節點數。這樣作能夠避免腦裂的現象都出現,最大限度地提高集羣的高可用性。只要很多於discovery.zen.minimum_master_nodes個候選節點存活,選舉工做就能夠順利進行。

5.4 Elasticsearch實戰

5.4.1 Elasticsearch的配置說明

 在Elasticsearch安裝目錄下的conf文件夾中包含了一個重要的配置文件:elasticsearch.yaml。
 Elasticsearch的配置信息有不少種,大部分配置均可以經過elasticsearch.yaml和接口的方式進行。下面咱們列出一些比較重要的配置信息。

  • cluster.name: elasticsearch:配置Elasticsearch的集羣名稱,默認值是elasticsearch,建議改爲與所存數據相關的名稱,Elasticsearch會自動發如今同一網段下的集羣名稱相同的節點。
  • node.nam: "node1":集羣中的節點名,在同一個集羣中不能重複。節點的名稱一旦設置,就不能再改變了。固然,也能夠設置成服務器的主機名稱,例如node.name:${HOSTNAME}。
  • noed.master: true:指定該節點是否有資格被選舉成爲Master節點,默認是true,若是被設置爲true,則只是有資格成爲Master節點,具體可否成爲Master節點,須要經過選舉產生。
  • node.data: true:指定該節點是否存儲索引數據,默認位true。數據的增、刪、改、查都是在Data節點完成的。
  • index.number_of_shards: 5:設置默認都索引分片個數,默認是5片。也能夠在建立索引時設置該值,具體設置爲多大都值要根據數據量的大小來定。若是數據量不大,則設置成1時效率最高。
  • index.number_of_replicas: 1:設置默認的索引副本個數,默認爲1個。副本數越多,集羣的可用性越好,可是寫索引時須要同步的數據越多。
  • path.conf: /path/to/conf:設置配置文件的存儲路徑,默認是Elasticsearch目錄下的conf文件夾。建議使用默認值。
  • path.data: /path/to/data1,/path/to/data2:設置索引數據多存儲路徑,默認是Elasticsearch根目錄下的data文件夾。切記不要使用默認值,由於若Elasticsearch進行了升級,則有可能數據所有丟失。能夠用半角逗號隔開設置的多個存儲路徑,在多硬盤的服務器上設置多個存儲路徑是頗有必要的。
  • path.logs: /path/to/logs:設置日誌文件的存儲路徑,默認是Elasticsearch根目錄下的logs,建議修改到其餘地方。
  • path.plugins:/path/to/plugins:設置第三方插件的存放路徑,默認是Elasticsearch根目錄下的plugins文件夾。
  • bootstrap.mlockall: true:設置爲true時可鎖住內存。由於當JVM開始swap時,Elasticsearch的效率會下降,因此要保證它不swap。
  • network.bind_host: 192.168.0.1:設置本節點綁定的IP地址,IP地址類型是IPv4或IPv6,默認爲0.0.0.0。
  • network.publish_host: 192.168.0.1:設置其餘節點和該節點交互的IP地址,若是不設置,則會進行自我判斷。
  • network.host: 192.168.0.1:用於同時設置bind_host和publish_host這兩個參數。
  • http.port:9200:設置對外服務的HTTP端口,默認爲9200。Elasticsearch的節點須要配置兩個端口號,一個對外提供服務的端口號,一個是集羣內部使用的端口號。http.port設置的是對外提供服務的端口號。注意,若是再一個服務器上配置多個節點,則切記對端口號進行區分。
  • transport.tcp.port: 9300:設置集羣內部的節點間交互的TCP端口,默認是9300.注意,若是在一個服務器配置多個節點,則切記對端口號進行區分。
  • transport.tcp.compress: true:設置在節點間傳輸數據時是否壓縮,默認爲false,不壓縮。
  • discovery.zen.minimum_master_nodes: 1:設置在選舉Master節點時須要參與的最少的候選主節點數,默認爲1.若是使用默認值,則當網絡不穩定時有可能會出現腦裂。合理的數值爲(master_eligible_nodes/2)+1,其中master_eligible_nodes表示集羣中的候選主節點數。
  • discovery.zen.ping.timeout: 3s:設置在集羣中自動發現其餘節點時ping鏈接的超時時間,默認爲3秒。在較差的網絡環境下須要設置得大一點,防止因誤判該節點的存活狀態而致使分片的轉移。

5.4.2 經常使用接口

 雖然如今有不少開源軟件對Elasticsearch的接口進行了封裝,使咱們能夠很方便、直觀地監控集羣的情況,可是在Elasticsearch 5之後,不少軟件開始收費。瞭解經常使用的接口有助於咱們在程序或者腳本中查看咱們的集羣狀況,如下接口適用於Elasticsearch 6.5.2版本。

1. 索引類接口
  • 經過下面的接口建立一個索引名稱爲indexname且包含3個分片、1個副本的索引。
PUT http://localhost:9200/indexname?pretty content-type →application/json; charset=UTF-8 { "settings":{ "number_of_shards" : 3, "number_of_replicas" : 1 } } 
 
建立索引
  • 經過下面都接口刪除索引:
DELETE http://localhost:9200/indexname 

 

 
刪除索引

 經過該接口就能夠刪除索引名稱爲indexname的索引。
 經過下面的接口能夠刪除多個索引。

 

DELETE http://localhost:9200/indexname1,indexname2 DELETE http://localhost:9200/indexname* 

 經過下面的接口能夠刪除集羣下的所有索引。

DELETE http://localhost:9200/_all DELETE http://localhost:9200/* 

 進行所有索引刪除是很危險的,咱們能夠經過在配置文件中添加下面的配置信息,來關閉使用_all和使用通配符刪除索引的接口,使用刪除索引職能經過索引的全稱進行。

action.destructive_requires_name: true 
  • 經過下面的接口獲取索引的信息,其中,pretty參數用語格式化輸出結構,以便更容易閱讀。
GET http://localhost:9200/indexname?pretty 
 
查詢索引
  • 經過下面的接口關閉、打開索引。
POST http://localhost:9200/indexname/_close POST http://localhost:9200/indexname/_open 
 
打開關閉索引
  • 經過下面的接口獲取一個索引中具體type的mapping映射。
GET http://localhost:9200/indexname/typename/_mapping?pretty 

 當一個索引中有多個type時,得到mapping時要加上typename。

二、document操做

 安裝ES和Kibana以後,進入Kibana操做頁面,而後進去的DevTools執行下面操做:

#添加一條document PUT /test_index/test_type/1 { "test_content":"test test" } #查詢 GET /test_index/test_type/1 #返回 { "_index" : "test_index", "_type" : "test_type", "_id" : "1", "_version" : 2, "found" : true, "_source" : { "test_content" : "test test" } } 
 
添加document

 
查詢document

 put /index/type/id,說明以下:

  • _index元數據:表明這個document存放在哪一個idnex中,相似的數據放在一個索引,非相似的數據放不一樣索引,index中包含了不少相似的document。
  • _type元數據:表明document屬於index中的哪一個類別(type),一個索引一般會劃分多個type,邏輯上對index中有些許不一樣的幾類數據進行分類。
  • _id元數據:表明document的惟一標識,id與index和type一塊兒,能夠惟一標識和定位一個document,能夠理解爲數據庫中主鍵。咱們能夠指定document的id,也能夠不指定,由ES自動爲咱們建立一個id。

5.4.3 接口應用

一、search接口

 search是咱們最經常使用的API,ES給我提供了豐富的查詢條件,好比模糊匹配match,字段判空exists,精準匹配term和terms,範圍匹配range

GET /_search
{
  "query": { "bool": { "must": [ //must_not { "match": { "title": "Search" }}, { "match": { "content": "Elasticsearch" }}, {"exists":{"field":"字段名"}} //判斷字段是否爲空 ], "filter": [ { "term": { "status": "published" }}, { "terms": { "status": [0,1,2,3] }},//範圍 { "range": { "publish_date": { "gte": "2015-01-01" }}} //範圍gte:大於等於;gt:大於;lte:小於等於;lt:小於 ] } } } 

 查詢索引爲test_index,doc類型爲test_type的數據。

GET /test_index/test_type/_search
 
ES查詢一

 查詢索引爲test_index,doc類型爲test_type,docment字段num10爲4的數據

GET /test_index/test_type/_search?pretty=true { "query": { "bool": { "filter": [ { "term": { "num10": 4 }} ] } } } 
 
ES精確查詢.png

 更多查詢條件的組合,你們能夠自行測試。

二、修改mapping
PUT /my_index/_mapping/my_type
{
  "properties": { "new_field_name": { "type": "string" //字段類型,string、long、boolean、ip } } } 

 如上是修改mapping結構,而後利用腳本script給字段賦值:

POST my_index/_update_by_query
{
  "script": { "lang": "painless", "inline": "ctx._source.new_field_name= '02'" } } 
三、修改別名

 以下給index爲test_index的數據綁定alias爲test_alias

POST /_aliases
{
  "actions": [ { "add": { //add,remove "index": "test_index", "alias": "test_alias" } } ] } 
 
新增別名關聯

 驗證別名關聯,根據別名來進行數據查詢,以下:

GET /test_alias/test_type/3
 
根據別名操做es數據
四、定製返回內容

 _source元數據:就是說,咱們在建立一個document的時候,使用的那個放在request body中的json串(全部的field),默認狀況下,在get的時候,會原封不動的給咱們返回回來。

定製返回的結果,指定_source中,返回哪些field。

#語法: GET /test_index/test_type/1?_source=test_field2 #返回 { "_index" : "test_index", "_type" : "test_type", "_id" : "1", "_version" : 3, "found" : true, "_source" : { "test_field2" : "test field2" } } #也可返回多個field使用都好分割 GET /test_index/test_type/1?_source=test_field2,test_field1 
 
_source測試

 
_source定製返回內容

5.4.4 JAVA封裝

 組件elasticsearch.jar提供了豐富API,不過不利於咱們理解和學習,如今咱們本身來進行封裝。
 組件API使用RestClient封裝document查詢接口:

/** * @param index * @param type * @param id * @param fields * 查詢返回字段,可空 * @return * @throws Exception * @Description: * @create date 2019年4月3日下午3:12:40 */ public String document(String index, String type, String id, List<String> fields) throws Exception { Map<String, String> paramsMap = new HashMap<>(); paramsMap.put("pretty", "true"); if (null != fields && fields.size() != 0) { String fieldValue = ""; for (String field : fields) { fieldValue += field + ","; } if (!"".equals(fieldValue)) { paramsMap.put("_source", fieldValue); } } return CommonUtils.toString(es.getRestClient() .performRequest("GET", "/" + index + "/" + type + "/" + id, paramsMap).getEntity().getContent()); } 

 工程使用,封裝:

public String searchDocument(String index, String type, String id, List<String> fields) { try { return doc.document(index, type, id, fields); } catch (Exception e) { log.error(e.getMessage()); ExceptionLogger.log(e); throw new RuntimeException("ES查詢失敗"); } } 

 測試用例,代碼以下:

/** * ES交互驗證-查詢、更新等等操做 * * @version * @author 錢丁君-chandler 2019年4月3日上午10:27:28 * @since 1.8 */ @RunWith(SpringRunner.class) @SpringBootTest(classes = Bootstrap.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class ESManagerTest { @Autowired private ESBasicManager esBasicManager; @Test public void query() { String result = esBasicManager.searchDocument(ESTagMetadata.INDEX_ALIAS, ESTagMetadata.DOC_TYPE, "188787665220752824", ImmutableList.of("signup_time", "tag_days_no_visit_after_1_order")); System.out.println("----------->" + result); } } 

 控臺輸出:

----------->{
  "_index" : "crm_tag_idx_20181218_708672", "_type" : "crm_tag_type", "_id" : "188787665220752824", "_version" : 1, "found" : true, "_source" : { "signup_time" : "2017-12-24", "tag_days_no_visit_after_1_order" : "339" } } 

 我只是拋磚引玉,你們能夠自行進行各類操做的封裝,無論對於理解ES的使用,仍是對代碼質量提高都有不少幫助。

最後謝謝你們觀賞

《Elasticsearch詳解》

若是須要給我修改意見的發送郵箱:erghjmncq6643981@163.com資料參考:《可伸縮服務架構》轉發博客,請註明,謝謝。

相關文章
相關標籤/搜索