1、概念
ElasticSearch是一個高性能,基於Lucene的全文檢索服務,是一個分布式的Restful風格的搜索和數據分析引擎,也可以作為NoSQL數據庫使用。Lucene 是apache軟件基金會一個開放源代碼的全文檢索引擎工具包,是一個全文檢索引擎的架構,提供了完整的查詢引擎和索引引擎,部分文本分析引擎。Lucene的目的是為軟件開發人員提供一個簡單易用的工具包,以方便的在目標系統中實現全文檢索的功能,或者是以此為基礎建立起完整的全文檢索引擎(搜索引擎和檢索程序庫不完全等同)。 lucene,最先進、功能最強大的搜索庫,直接基於lucene開發,非常復雜,api復雜(實現一些簡單的功能,寫大量的java代碼),需要深入理解原理(各種索引結構)。elasticsearch,基於lucene,隱藏復雜性,提供簡單易用的restful api接口、java api接口
- 對Lucene進行了擴展,提供了比Lucene更為豐富的查詢語言,同時實現了可配置、可擴展,並對查詢性能進行了優化,還提供了一個完善的功能管理界面。
- 原型環境和生產環境可無縫切換,無論ElasticSearch是在一個節點上運行,還是在一個包含300節點的集群上運行,都能夠以相同的方式與ElasticSearch進行通信。
- 能夠水平擴展,每秒鍾可處理海量事件,同時能夠自動管理索引和查詢在集群中的分布方式,以實現極其流暢的操作。
- 支持結構化和非結構化數據,支持數字、文本、地理位置、即結構化和非結構化數據。
2、特點
- 高性能/速度 能立即獲得搜索結果。我們通過有限狀態轉換器實現了用於全文檢索的倒排索引,實現了用於存儲數值數據和地理位置數據的 BKD 樹,以及用於分析的列存儲。由於每個數據都被編入了索引,就不必擔心某些數據沒有索引。
- 可擴展性 可以在筆記本電腦上運行。也可在承載了 PB 級數據的成百上千台服務器上運行。 原型環境和生產環境可無縫切換;無論是在一個節點上運行,還是在一個包含 300 個節點的集群上運行,您都能夠以相同的方式與 Elasticsearch 進行通信。 能夠水平擴展,每秒鍾可處理海量事件,同時能夠自動管理索引和查詢在集群中的分布方式,以實現極其流暢的操作。
- 相關度 搜索所有內容。找到所需的具體信息。基於各項元素(從詞頻或近因到熱門度等)對搜索結果進行排序。將這些內容與功能進行混合和匹配,以對向用戶顯示結果的方式進行微調。Elasticsearch 功能齊全,可以處理包括各種復雜情況(例如拼寫錯誤)在內的人為錯誤。
- 可靠性 /彈性 硬件故障。網絡分割。Elasticsearch 為您檢測這些故障並確保您的集群(和數據)的安全性和可用性。跨集群復制功能,輔助集群可作為熱備份隨時投入使用。Elasticsearch 運行在一個分布式的環境中,從設計之初就考慮到了這一點,目的就是讓您永遠高枕無憂。
3、應用場景
用於日志搜索和分析、時空檢索、時序檢索、智能搜索等場景。
檢索的數據類型復雜:如需要查詢的數據有結構化數據、半結構化數據、非結構化數據等,ElasticSearch可以對以上數據類型進行清洗、分詞、建立倒排索引等一系列操作,然后提供全文檢索的能力。
檢索條件多樣化:全文檢索條件可以包括詞或短語。
邊寫邊讀:寫入的數據可以實時的進行檢索。
4、插件擴展層:
- Logstash:具備實時數據傳輸能力的管道,着重日志相關處理;負責將數據信息從管道的輸入端傳輸到管道的輸出端;支持靈活根據自己的需求在中間加上濾網,Logstash提供里很多功能強大的濾網以滿足你的各種應用場景
- Kibana;開源的分析和可視化平台,數據主要由es提供;基於es的搜索與分析能力,拿到用於上層分析和可視化需要的結果;開發者或運維人員可以輕松地執行高級數據分析,並在各種圖表、表格和地圖中可視化數據。
- Beats:專門用於發送數據的平台,可以將數據無縫傳輸給logstash或是es;輕量級代理機制安裝,類似於hadoop集群安裝時候的ambari或cdh manager;可將數以百千計算機中的數據發送到logstash或是es中。
- es-hadoop:一個深度集成Hadoop和es的項目,是es官方維護的一個子項目;可以達到hadoop與es之間的輸入與輸出;重點是充分利用Map-Reduce的並行計算優勢,為hdfs數據提供實時搜索能力。
- es-sql:用sql來操作es,來代替之前需要寫各種復雜的json查詢才可解決的問題;es-sql目前有兩個版本,第一,是多年前即開始的國內主推開源的nlpchina/es-sql插件,第二,是自2018.06官方es6.3.0發布后正式支持的es-sql功能。
- elasticsearch-head:將是一款專門針對於elasticsearch的客戶端工具,是一個界面化的集群操作和管理工具,可以對集群進行傻瓜式操作,是一個基於node.js的前端工程,
- Bigdesk:是elasticsearch的一個集群監控工具,可以通過它來查看es集群的各種狀態,如:cpu、內存使用情況,索引數據、搜索情況,http連接數等。
5、整體架構
- Cluster:代表一個集群,集群中有多個節點,其中有一個為主節點,這個主節點是可以通過選舉產生的,主從節點是對於集群內部來說的。
- EsNode:ElasticSearch節點,一個節點就是一個ElasticSearch實例。
- EsMaster:主節點,可以臨時管理集群級別的一些變更,例如新建或刪除索引、增加或移除節點等。主節點不參與文檔級別的變更或搜索,在流量增長時,該主節在流量增長時,該主節點不會成為集群的瓶頸。
- shards:代表索引分片,ElasticSearch可以把一個完整的索引分成多個分片,這樣的好處是可以把一個大的索引拆分成多個,分布到不同的節點上。
- replicas:代表索引副本,ElasticSearch可以設置多個索引的副本,副本的作用一是提高系統的容錯性,當某個節點某個分片損壞或丟失時可以從副本中恢復。二是提高Elasticsearch的查詢效率,Elasticsearch會自動對搜索請求進行負載均衡。
- 高性能:虛擬內存設計;磁盤緩存相關參數;swap調優;replica數目;refresh時間間隔;merge相關參數;mapping設置;定期清理cache
- 多租戶:支持多租戶;ES實例數根據服務器內存設置,ES單節點實例數 = ES的可用的內存 / 64GB;服務器邏輯磁盤數要跟ES實例數一致,因此ES服務器需要按照實例數做Raid,例如推薦配置256G內存,24塊磁盤,那么ES實例數 = 4,需要做4組Raid,每組6塊磁盤
核心概念
- Index:即索引,是ElasticSearch中一個邏輯命名空間,指向一個或多個分片,內部 Apache Lucene實現索引中數據的讀寫。索引與關系數據庫實例Database相當。一個 Elasticsearch 實例可以包含多個索引。
- Type:文檔類型,文檔類型使得同一個索引中在存儲結構不同的文檔時,只需要依據文檔類型就可以找到對應的參數映射信息,方便文檔的存儲。相當於數據庫中的Table。一個索引對應一個文檔類型。
- Document :文檔,是可以被索引的基本單位,特指最頂層結構或根對象序列化成的 JSON數據。通過相當於數據庫中的Row。一個類型包含多 Mapping:映射,用來約束字段的類型,可以根據數據自動創建。相當於數據庫中的 Shema。
- recovery: 代表數據恢復或叫數據重新分布,Elasticsearch在有節點加入或退出時會根據機器的負載對索引分片進行重新分配,掛掉的節點重新啟動時也會進行數據恢復。
內部架構
- 接口:通過java ,restful api 提供豐富接口,底層基於lucence,通過本地文件,共享文件,hdfs完成索引存儲
- JMX(Java Management Extensions,即Java管理擴展)是一個為應用程序、設備、系統等植入管理功能的框架。JMX可以跨越一系列異構操作系統平台、系統體系結構和網絡傳輸協議,靈活的開發無縫集成的系統、網絡和服務管理應用。
- Lucence Directory: 是lucene的框架服務發現以及選主 ZenDiscovery: 用來實現節點自動發現,還有Master節點選取,假如Master出現故障,其它的這個節點會自動選舉,產生一個新的Master
- Plugins:插件可以通過自定的方式擴展加強Elasticsearch的基本功能,比如可以自定義類型映射,分詞器,本地腳本,自動發現等
- Scripting:使用腳本語言可以計算自定義表達式的值,比如計算自定義查詢相關度評分。支持的腳本語言有groovy,js,mvel(1.3.0廢棄),python等
- Disovery:該模塊主要負責集群中節點的自動發現和Master節點的選舉。節點之間使用p2p的方式進行直接通信,不存在單點故障的問題。Elasticsearch中,Master節點維護集群的全局狀態,比如節點加入和離開時進行shard的重新分配
- River:代表es的一個數據源,也是其它存儲方式(如:數據庫,官方的river有couchDB的,RabbitMQ的,Twitter的,Wikipedia等)同步數據到es的一個方法。它是以插件方式存在的一個es服務,通過讀取river中的數據並把它索引到es中。
- gateway: 代表Elasticsearch索引快照的存儲方式,Elasticsearch默認是先把索引存放到內存中,當內存滿了時再持久化到本地硬盤。gateway對索引快照進行存儲,當這個Elasticsearch集群關閉再重新啟動時就會從gateway中讀取索引備份數據。Elasticsearch支持多種類型的gateway,有本地文件系統(默認),分布式文件系統,Hadoop的HDFS和amazon的s3雲存儲服務。
- transport: 代表Elasticsearch內部節點或集群與客戶端的交互方式,默認內部是使用tcp協議進行交互,同時它支持http協議(json格式)、thrift、servlet、memcached、zeroMQ等的傳輸協議(通過插件方式集成)。
6、緩存機制
ElasticSearch緩存主要分三種:Query Cache、Fielddata Cache、Request Cache。
- Query Cache:屬於Node級別的緩存,是對一個查詢中包含的過濾器執行結果進行緩存。就是對一個查詢中包含的過濾器執行結果進行緩存。常用的term,terms,range過濾器都會在滿足某種條件后被緩存。主要用於緩存Filter中的Query結果,基於LRU策略,當緩存滿了的情況下,會自動去除一個最近最少被使用的Query Cache。
- Fielddata Cache:Fielddata是專門針對分詞的字段在查詢期間的數據結構的緩存。當我們第一次在一個分詞的字段上執行聚合、排序或通過腳本訪問的時候就會觸發該字段Fielddata Cache的加載,這種緩存是“segment”級別的,當有新的segment打開時舊的緩存不會重新加載,而是直接把新的segement對應的Fielddata Cache加載到內存。加載Fielddata Cache是一個非常昂貴的操作,一旦Fielddata被加載到內存,那么在該Fielddata Cache對應的Segement生命周期范圍內都會駐留在內存中。也就是說當段合並時會觸發合並后更大段的Fielddata Cache加載。Fielddata會消耗大部分的JVM堆內存,特別是當加載“高基數”的分詞字段時(那些分詞后存在大量不同詞的字段),針對這種字段的聚合排序其實是非常沒有意義的,我們更多的要去考慮是否能用not_analyzed代替(這樣就可以使用doc_values實現聚合、排序)。默認開啟的。
- Request Cache:Shard級別的緩存,是為了緩存“分片級”的本地結果集。目前只會緩存查詢中參數size=0的請求,所以就不會緩存hits 而是緩存 hits.total,aggregations和suggestions。Request Cache是非常智能的,它能夠保證和在近實時搜索中的非緩存查詢結果一致。默認情況下Request Cache是關閉的,需要手動開啟。
7、索引流程
客戶端發送批量索引請求至任意節點后,節點將轉發請求至對應主分片節點,主分片節點按序操作,完成一個操作后再發送給其余復制節點執行。復制節點操作完成報告給主分片節點,主分片節點報告給請求節點並返回至客戶端。
- 階段1:客戶端向Node 1發送大量(bulkv)請求。
- 階段2:Node 1為每個分片構建批量請求,然后轉發到這些請求所需的主分片上。
- 階段3:主分片一個接一個的按序執行操作。當一個操作執行完,主分片轉發新文檔(或者刪除部分)給對應的復制節點,然后
- 執行下一個操作。復制節點為報告所有操作完成,節點報告給請求節點,請求節點整理響應並返回給客戶端
傳統的搜索方式(正排序索引)是從關鍵點出發,通過正排序索引進行搜索,就是從通過文檔編號找關鍵詞。 ElasticSearch(Lucene)的搜索采用了倒排序索引的方式,而在全文搜索中Value就是我們要搜索的關鍵詞,存放所有關鍵詞的地方叫詞典 Key是文檔標號列表(通過文檔標號列表我們可以找到出現過要搜索關鍵詞--Value的文檔),具體如下面的圖所示:通過倒排索引進行搜索,就是通過關鍵詞查詢對應的文檔編號,再通過文檔編號找文檔,類似於查字典,或通過查書目錄查指定頁碼書的內容。
- 正排索引:是通過Key尋找Value,即從關鍵點出發,然后再通過關鍵點找到信息中滿足搜索條件的特定信息。
- 倒排索引:ElasticSearch所采用得排序方式,是通過Value找Key。而在全文搜索中Value就是要搜索的關鍵詞,通過Value找到對應的文檔。
8、搜索流程
節點收到所有待檢索的數據后,發送請求給數據相關的分片,收到請求的分片節點會讀取數據並返回給檢索節點,檢索節點匯總結果並返回給客戶端。
搜索流程分為兩個階段,即查詢階段與獲取階段。查詢階段主要定位了所要檢索數據的具體位置,而獲取階段的任務就是將這些定位好的數據內容取回並返回給客戶端
- 查詢階段: 階段1:客戶端發送一個檢索請求給任意節點,假設是Node 3。 階段2:Node 3將檢索請求發送給該index中的每一個shard,此時會采取輪詢策略,在primary shard及其所有replica中隨機選擇一個,讓讀請求負載均衡。每個shard在本地執行檢索,並將結果排序添加到本地。 階段3:每個shard返回本地所記錄的結果,發送給Node 3。Node 3將這些值合並,做全局排序。
- 獲取階段: 階段1:Node 3獲取了所有待檢索數據的定位之后,發送請求給與數據相關的shard。 階段2:每個收到Node 3請求的shard,將讀取相關文檔中的內容,並將它們返回給Node 3。 階段3:當Node 3獲取到了所有shard返回的文檔后,Node 3將它們合並成一條匯總結果,返回給客戶端。
批量搜索流程
客戶端發送批量搜索請求至任意節點,該節點為每個分片分別構建一個多條數據檢索請求,然后轉發至主分片或副本分片。當所有請求執行完成后,請求節點匯總記錄並返回給客戶端。
階段1:客戶端向Node 1 發送mget 請求。
階段2:Node 1 為每個分片構建一個多條數據檢索請求,然后轉發到這些請求所需的主分片或副本分片上。當所有回復被接收,Node 1 構建響應並返回給客戶端。
9、性能優化
索引一旦創建好后,就無法調整分片的數量,而ElasticSearch一個分片實際上對應一個存儲數據Lucene索引,Lucene索引的讀寫會占用很多的系統資源,因此,分片副本數需要合理的配置:
- 分片數不超過節點數的3倍,用較少的分片獲得更佳的性能。
- 副本數建議設置為1,過多的副本需要更多存儲空間。
- 分片最大容量不要超過ElasticSearch推薦的最大JVM堆空間32G。
- Lucene索引,即索引文件格式。結構如下:索引(Index):對應一個文件夾中的;段(Segment):一個索引可以包含多個段,段之間獨立,添加新文檔可以生成新的段,不同的段可以合並。相同前綴文件的屬同一個段。segments.gen和segments_5是段的元數據文件,也即它們保存了段的屬性信息。文檔(Document):建索引的基本單位,不同的文檔是保存在不同的段中的,一個段可以包含多篇文檔;域(Field):一篇文檔包含不同類型的信息,可以分開索引,比如標題,時間,正文,作者等,都可以保存在不同的域里;詞(Term):詞是索引的最小單位,是經過詞法分析和語言處理后的字符串。
- 1個Elasticsearch的索引有1個或者多個分片。分片對應實際存儲數據的Lucene的索引,分片自身就是一個搜索引擎。Elasticsearch的索引還包含"type"(就像數據庫中的表),用於邏輯上隔離索引中的數據。
- 如果分片數過多,大大超過了節點數,很可能會導致一個節點上存在多個分片,一旦該節點故障,即使保持了1個以上的副本,同樣有可能會導致數據丟失,集群無法恢復。
- Elasticsearch6.X及之前的版本默認索引分片數為5、副本數為1,從Elasticsearch7.0開始調整為默認索引分片數為1、副本數為1
- 100個分片, 即便很少使用也可能是好的;而2個分片, 即便使用非常頻繁, 也可能是多余的。
- jvm內存建議不要低於2G,否則有可能因為內存不足導致ES無法正常啟動或內存溢出,jvm建議不要超過32G,否則jvm會禁用內存對象指針壓縮技術,造成內存浪費。32G性能不如40G
- indices.recovery.max_bytes_per_sec:索引恢復每秒最大字節數,默認值為40MB,調整此參數可以使索引恢復的網絡帶寬增加。
- cluster.routing.allocation.cluster_concurrent_rebalance:控制集群范圍允許多少個並發碎片重新平衡。默認值為2。請注意,此參數僅控制由於群集中的不平衡而導致的並發碎片重定位的數量。