一文讀懂ES基礎概念及索引過程

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

下面簡單介紹一下ES中的基礎概念:1.ES集羣Elasticsearch是一個分佈式系統,具備高可用性及可擴展性,當集羣中有節點中止或丟失時不會影響集羣服務或形成數據丟失;同時當訪問量或數據量增長時可用採用橫向擴展的方式增長節點,將請求或數據分散到集羣的各個節點上。不一樣的集羣能夠經過不一樣的名字來區分,集羣默認名爲「elasticsearch「,若是節點配置的集羣名稱同樣,則這些節點組成爲一個ES集羣。2.ES節點一個節點是一個ElasticSearch的實例,本質上是一個Java進程。ES根據功能不一樣分爲不一樣的節點類型,在生產環境中,建議根據數據量,寫入及查詢吞吐量,選擇合適的部署方式,最好將節點設置爲單一角色。node

節點類型 節點做用 節點配置參數 默認值
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

3.ES文檔文檔是ES的最小單位,一般用JSON方式的數據結構表示,相似於數據庫中的一條記錄。文檔具備如下特徵:1.自我包含,一篇文檔同時包含字段和它們的取值。2.層次型結構,文檔中能夠包含新的文檔。3.靈活的結構,不依賴於預先定義的模式,文檔是無模式的,並不是全部的文檔都須要擁有相同的字段。4.ES類型類型是文檔的邏輯容器,相似於數據庫中的表,類型在 Elasticsearch中表示一類類似的文檔,每一個類型中字段的定義稱爲映射。ES7.x已經將類型移除,7.x中一個索引只能有一個類型,默認爲_doc。5.ES映射mapping映射, 就像數據庫中的 schema ,定義索引中字段的名稱、字段的數據類型(如 string, integer 或 date),設置字段倒排索引的相關配置。當索引文檔遇到未定義的字段,會使用dynamic mapping 來肯定字段的數據類型,並自動把新增長的字段添加到類型映射。在實際生產中通常或禁用dynamic mapping,避免過多的字段致使cluster state佔用過多,同時禁止自動建立索引的功能,建立索引時必須提供Mapping信息或者經過Index Template建立。6.ES索引  ES索引是映射類型的容器,相似於數據庫。7.ES分片一個分片是一個運行的Lucene的實例,是一個包含倒排索引的文件目錄。一個ES索引由一個或多個主分片以及零個或多個副本分片組成,主分片數在索引建立時指定,後續不容許修改;副本分片主要用於解決數據高可用的問題,是主分片的拷貝,必定程度上提升服務的可讀性。分片的設定:生產環境中主分片數的設定,須要提早作好容量規劃,由於主分片的數量是不可修改的。若是分片數設置太小,則沒法經過增長節點實現水平擴展,單個分片的數據量太大,致使數據從新分片耗時;若是分片數設置過大,則會影響搜索結果的相關性打分,浪費資源,同時影響性能。在瞭解了ES的基本概念以後,咱們經過一張圖來探索一下ES索引的全流程: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等,同時也支持經過插件的方式,實現自定義的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;詞頻:記錄單詞在文檔中出現的次數;位置:記錄單詞在文檔中的位置;偏移:記錄單詞的開始位置,結束位置。
DocId(文檔ID) TF(詞頻) position(位置) offset(偏移)
1 1 10 <10,20>
2 1 0 <0,5>

  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風格接口,方便應用接入使用;適用於全部的數據類型,具有存儲海量數據能力,擁有高性能的近實時檢索功能,同時還提供了數據的近實時分析功能;適用於海量數據的近實時檢索、分析,在日誌、監控數據存儲分析,集中式全文搜索方面應用較爲普遍。數據庫

相關文章
相關標籤/搜索