ElasticSearch基本概念及索引過程


ElasticSearch概述

Elasticsearch是一個近實時分布式搜索引擎,其底層基於開源全文搜索庫Lucene;Elasticsearch對Lucene進行封裝,對外提供REST API 的操作接口。基於 ES,可以快速的搭建全文搜索引擎;除了搜索功能,ES還可以對數據進行分析:如日志分析、指標分析,同時還提供了機器學習功能。Elasticsearch有一個完整的生態圈(ELK),形成了從數據采集(logstash,filebeat)、數據存儲(Elasticsearch)、數據可視化(kibana)的閉環。

ES屬於面向文檔(Document Oriented)的,這意味着它可以存儲整個對象或者文檔數據(Document),然而,它不僅僅是存儲,還有索引(index)每一個文檔的內容使之可以被搜索,可以對文檔進行索引,搜索,排序,過濾,分詞,高亮顯示。ES比傳統關系型數據庫查詢更加迅速。

ES中每一個運行的實例都被稱為一個節點(node),實例即可在同一個機器上運行也可以在不同的機器上運行。一個ES集群是由一個或者多個ES節點組成的集合,這個集群里有一個節點叫主節點(master),節點可以存儲數據,參與索引數據等的獨立服務。而且ES是去中心化的,所以主節點是動態選舉出來的,不存在單點故障

ES的特性:

  • 速度快、易擴展、彈性、靈活、操作簡單、多語言客戶端、X-Pack、hadoop/spark強強聯手、開箱即用。
  • 分布式:橫向擴展非常靈活
  • 全文檢索:基於lucene的強大的全文檢索能力;
  • 近實時搜索和分析:數據進入ES,可達到近實時搜索,還可進行聚合分析
  • 高可用:容錯機制,自動發現新的或失敗的節點,重組和重新平衡數據
  • 模式自由:ES的動態mapping機制可以自動檢測數據的結構和類型,創建索引並使數據可搜索。
  • RESTful API:JSON + HTTP

ElasticSearch基本概念

集群

集群由一個或多個節點組成,對外提供服務,索引和搜索功能。在所有的節點中,一個集群有一個唯一的名稱默認為“elasticsearch”,此名稱很重要,因為每個節點只能是集群的一部分,當該節點被設置為相同的集群名稱時,就會自動加入集群。當需要多個集群的時候,要確保每個集群的名稱不能重復,否則,節點可能會加入錯誤的集群。

當集群中有節點停止或丟失時不會影響集群服務或造成數據丟失;同時當訪問量或數據量增加時可用采用橫向擴展的方式增加節點,將請求或數據分散到集群的各個節點上。

節點

一個節點是你集群中的一個服務器,作為集群的一部分,它存儲你的數據,參與集群的索引和搜索功能。和集群類似,一個節點也是由一個名字來標識的。

一個節點是一個ElasticSearch的實例,本質上是一個Java進程。ES根據功能不同分為不同的節點類型,在生產環境中,建議根據數據量,寫入及查詢吞吐量,選擇合適的部署方式,最好將節點設置為單一角色。

節點類型 節點作用 節點配置參數 默認值
Master Node 管理節點,進行創建、刪除索引等操作,決定分片被分配到哪個節點,負責索引創建刪除,維護並更新集群狀態。 node.master true  
Data Node 數據節點,處理與數據相關的操作,如索引的CRUD、搜索和聚合,數據節點的操作屬於I/O、內存和CPU密集型操作。 node.data true 
Ingest Node 提取節點,具有數據預處理的能力,可攔截Index或Bulk Api的請求,可對數據進行轉換,並重新返回Index或Bulk Api,默認配置下,所有節點都是Ingest Node。 node.ingest true 
Coordinating Node 協調節點,負責接受客戶端的請求,並將請求分發到合適的節點,並將各節點返回的數據匯聚到一起。每個節點都默認是Coordinating Node。 設置master、data、ingest全為false
Maching Learning Node 機器學習節點,用於運行作業和處理機器學習API請求。 node.ml true,需要enable x-pack

索引

一個索引就是一個擁有幾份相似特征的文檔的集合。比如說,你可以有一個客戶數據的索引,一個產品目錄的索引,還有一個訂單數據的索引。一個索引由一個名字來標識(必須全部是小寫字母的),並且當我們要對對應於這個索引中的文檔進行索引、搜索、更新和刪除的時候,都要使用到這個名字。在一個集群中,可以定義任意多的索引。

類型

類型是文檔的邏輯容器,類似於數據庫中的表,類型在 Elasticsearch中表示一類相似的文檔,每個類型中字段的定義稱為映射。ES7.x已經將類型移除,7.x中一個索引只能有一個類型,默認為_doc。

文檔

文檔是存儲在ES中的一個JSON字符串,相當於數據庫中表的一行,ES是一個非結構化的數據庫,每一個文檔可以有不同的字段,並且有一個唯一的標識符。

字段

類似關系型數據庫的某一列,這是ES數據存儲的最小單位。

映射

mapping映射, 就像數據庫中的 schema ,定義索引中字段的名稱、字段的數據類型(如 string, integer 或 date),設置字段倒排索引的相關配置。當索引文檔遇到未定義的字段,會使用dynamic mapping 來確定字段的數據類型,並自動把新增加的字段添加到類型映射。在實際生產中一般或禁用dynamic mapping,避免過多的字段導致cluster state占用過多,同時禁止自動創建索引的功能,創建索引時必須提供Mapping信息或者通過Index Template創建。

分片

一個分片是一個運行的Lucene的實例,是一個包含倒排索引的文件目錄。一個ES索引由一個或多個主分片以及零個或多個副本分片組成,主分片數在索引創建時指定,后續不允許修改;副本分片主要用於解決數據高可用的問題,是主分片的拷貝,一定程度上提高服務的可讀性。分片的設定:生產環境中主分片數的設定,需要提前做好容量規划,因為主分片的數量是不可修改的。如果分片數設置過小,則無法通過增加節點實現水平擴展,單個分片的數據量太大,導致數據重新分片耗時;如果分片數設置過大,則會影響搜索結果的相關性打分,浪費資源,同時影響性能。

備份

拷貝一個分片就完成了分片的備份,備份的好處:當主分片失敗或者掛掉, 備份就可以代替分片進行操作, 進而提高了es的可用性, 備份的分片還可以進行搜索操作, 以分攤搜索的壓力。ES在創建索引時, 默認創建5個分片, 一份備份, 可以修改, 分片的數量只能在創建索引的時候指定, 索引創建后就不能修改分片的數量了, 而備份是可以動態修改的。

數據庫與ES對比圖

注:在ES6.0.0及更高的版本中,創建的索引只能包含一個映射類型。在6.0.0以下的版本中創建的一個索引映射多個類型的索引在6.0.0版本中繼續發揮作用,但是將在7.0.0中完全刪除。

ES索引的全流程

1、客戶端發送索引請求

客戶端向ES節點發送索引請求,以RestClient客戶端發起請求為例,ES提供了Java High Level REST Client,可以通過RestClient發送請求:

RestClient restClient = RestClient.builder(
            new HttpHost("127.0.0.1", 9200, "http"),
            new HttpHost("127.0.0.2", 9200, "http")
           ).build();

其中127.0.0.1,127.0.0.2是ES節點地址,充當coordinate node節點的角色,接收客戶端請求,如果設置有專用coorinate node,則應該將接受客戶端請求的節點設置為該專用節點,負責請求的接受和轉發。在RestClient中使用round-robin輪詢算法,進行發送節點的選取。

2、參數檢查

對請求中的參數進行檢查,檢查參數是否合法,不合法的參數直接返回失敗給客戶端。

3、數據預處理

如果請求指定了pipeline參數,則對數據進行預處理,數據預處理的節點為Ingest Node,如果接受請求的節點不具備數據處理能力,則轉發給其他能處理的節點。在Ingest Node上有定義好的處理數據的Pipeline,Pipeline中有一組定義好的Processor,每個Processor分別具有不同的處理功能,ES提供了一些內置的Processor,如:split、join、set 、script等1,同時也支持通過插件的方式,實現自定義的Processor。數據經過Pipeline處理完畢后繼續進行下一步操作。

4、判斷索引是否存在

判斷索引是否存在。如果索引不存在,則判斷是否能夠自動創建,可以通過action.auto_create_index設置能否自動創建索引;如果節點支持Dynamic Mapping,寫入文檔時,如果字段尚未在mapping中定義,則會根據索引文檔信息推算字段的類型,但並不能完全推算正確。

配置:

  • Dynamic:true時,文檔有新增字段的時候,索引的mapping也會同步更新。
  • Dynamic:false時,索引的mapping不會被更新,新增字段無法被索引到。
  • Dynamic:strict時,索引有新增字段時,將會報錯。

5、創建索引

創建索引請求被發送到Master節點,由Master節點負責進行索引的創建,索引創建成功后,Master節點會更新集群狀態clusterstate,更新完畢后將索引創建的情況返回給Coordinate節點,收到Master節點返回后,進入下一流程。

6、請求預處理

(1)獲取集群狀態信息,判斷集群是否正常;

(2)從集群狀態中獲取對應索引的元信息,從元信息中獲取索引的mapping、version等信息,從請求中解析routing、id信息,如果請求沒有指定文檔的id,則會生成一個UUID作為文檔的id。

7、路由計算

根據請求的routing、id信息計算文檔應該被索引到哪個分片,計算公式為:shard_num = hash(_routing) % num_primary_shards。

其中_routing默認值為文檔id,num_primary_shards是主分片個數,所以從算法中即可以看出索引的主分片個數一旦指定便無法修改,因為文檔利用主分片的個數來進行定位。

當使用自定義_routing或者id時,按照上面的公式計算,數據可能會大量聚集於某些分片,造成數據分布不均衡,所以ES提供了routing_partition_size參數,routing_partition_size越大,數據的分布越均勻。此時分片的計算公式變為:shard_num = (hash(_routing) + hash(_id) % routing_partition_size) % num_primary_shards。

定位到分片序號后,還需要定位分片所屬的數據節點;從集群狀態的內容路由表獲取主分片所在的節點,並將請求轉發至節點。需要注意的是分片到數據節點的映射關系不是固定的,當檢測到數據分布不均勻、新節點加入或者節點宕掉等會進行分片的重新分配。

8、主分片索引分檔

當主分片所在節點接受到請求后,節點開始進行本節點的文檔寫入,文檔寫入過程:

(1)文檔寫入時,不會直接寫入到磁盤中,而是先將文檔寫入到Index Buffer內存空間中,到一定的時間,Index Buffer會Refresh把內存中的文檔寫入Segment中。當文檔在Index Buffer中時,是無法被查詢到的,這就是ES不是實時搜索,而是近實時搜索的原因

(2)文檔寫入時,先寫入到內存中,當文檔落盤之前,節點出現故障重啟、宕機等,會造成內存中的數據丟失,所以索引寫入的同時會同步向Transaction Log寫入操作內容。

(3)每隔固定的時間間隔ES會將Index Buffer中的文檔寫入到Segment中,這個寫入的過程叫做Refresh,Refresh的時間可以通過index.refresh_interval設置,默認情況下為1秒。

(4)寫入到Segment中並不代表文檔已經落盤,因為Segment寫入磁盤的過程相對耗時,Refresh時會先將Segment寫入緩存,開放查詢,也就是說當文檔寫入Segment后就可以被查詢到。每次refresh的時候都會生成一個新的segment,太多的Segment會占用過多的資源,而且每個搜索請求都會遍歷所有的Segment,Segment過多會導致搜索變慢,所以ES會定期合並Segment,減少Segment的個數,並將Segment合並為一個大的Segment;在操作Segment時,會維護一個Commit Point文件,其中記錄了所有Segment的信息;同時維護.del文件用於記錄所有刪除的Segment信息。單個倒排索引文件被稱為Segment。多個Segment匯總在一起,就是Lucene的索引,對應的就是ES中的shard。

Lucene倒排索引由單詞詞典及倒排列表組成:

  • 單詞詞典:記錄所有文檔的單詞,記錄單詞到倒排列表的關系,數據量比較大,一般采用B+樹,哈希拉鏈法實現。
  • 倒排列表:記錄單詞對應的文檔集合,由倒排索引項組成。

倒排索引項結構如表所示:文檔ID:記錄單詞所在文檔的ID;詞頻:記錄單詞在文檔中出現的次數;位置:記錄單詞在文檔中的位置;偏移:記錄單詞的開始位置,結束位置。

(5)每隔一定的時間(默認30分鍾),ES會調用Flush操作,Flush操作會調用Refresh將Index Buffer清空;然后調用fsync將緩存中的Segments寫入磁盤;隨后清空Transaction Log。當Transaction Log空間(默認512M)滿后也會觸發Flush操作。

9、副本分片索引文檔

當主分片完成索引操作后,會循環處理要寫的所有副本分片,向副本分片所在的節點發送請求。副本分片執行和主分片一樣的文檔寫入流程,然后返回寫入結果給主分片節點。

10、請求返回

主分片收到副本分片的響應后,執行finish()操作,將收到響應信息返回給Coordinate節點,告知Coordinate節點文檔寫入的情況;coordinate節點收到響應后,將索引執行情況返回給客戶端。至此一個文檔索引的全過程結束,用戶可通過ElasticSearch提供的接口進行數據的查詢。

ElasticSearch自誕生以來,使用熱度越來越高,功能越來越強大。ES不僅支持分布式、可擴展,還提供了RestFul風格接口,方便應用接入使用;適用於所有的數據類型,具備存儲海量數據能力,擁有高性能的近實時檢索功能,同時還提供了數據的近實時分析功能;適用於海量數據的近實時檢索、分析,在日志、監控數據存儲分析,集中式全文搜索方面應用較為廣泛。

 

參考:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM