前言
在前幾篇關於ElasticSearch的文章中,簡單的講了下有關ElasticSearch的一些使用,這篇文章講一下有關 ElasticSearch的一些理論知識以及自己的一些見解。
雖然本人是一個實戰派,不太喜歡講這些理論知識,因為這塊可以查看官方文檔,那里會寫得非常詳細,但是在使用了ElasticSearch之后,發現有的知識點需要掌握一定的理論知識才能理解,對於初學者來說有的不好理解,因此寫下該篇文章,希望讀者在看完之后能夠有所幫助。
ElasticSearch 理論知識介紹
ElasticSearch是什么
Elasticsearch 是一個基於JSON的分布式搜索和分析引擎。它可以從RESTful Web服務接口訪問,並使用模式少JSON(JavaScript對象符號)文檔來存儲數據。它是基於Java編程語言,這使Elasticsearch能夠在不同的平台上運行。使用戶能夠以非常快的速度來搜索非常大的數據量。
ElasticSearch可以做什么
- 分布式的實時文件存儲,每個字段都被索引並可被搜索
- 分布式的實時分析搜索引擎
- 可以擴展到上百台服務器,處理PB級結構化或非結構化數據
Lucene是什么
ApacheLucene將寫入索引的所有信息組織成一種倒排索引(Inverted Index)的結構之中,該結構是種將詞項映射到文檔的數據結構。其工作方式與傳統的關系數據庫不同,大致來說倒排索引是面向詞項而不是面向文檔的。且Lucene索引之中還存儲了很多其他的信息,如詞向量等等,每個Lucene都是由多個段構成的,每個段只會被創建一次但會被查詢多次,段一旦創建就不會再被修改。多個段會在段合並的階段合並在一起,何時合並由Lucene的內在機制決定,段合並后數量會變少,但是相應的段本身會變大。段合並的過程是非常消耗I/O的,且與之同時會有些不再使用的信息被清理掉。在Lucene中,將數據轉化為倒排索引,將完整串轉化為可用於搜索的詞項的過程叫做分析。文本分析由分析器(Analyzer)來執行,分析其由分詞器(Tokenizer),過濾器(Filter)和字符映射器(Character Mapper)組成,其各個功能顯而易見。
Elk架構
“ELK”是三個開源項目的首字母縮寫,這三個項目分別是:Elasticsearch、Logstash 和 Kibana。Elasticsearch 是一個搜索和分析引擎。Logstash 是服務器端數據處理管道,能夠同時從多個來源采集數據,轉換數據,然后將數據發送到諸如 Elasticsearch 等“存儲庫”中。Kibana 則可以讓用戶在 Elasticsearch 中使用圖形和圖表對數據進行可視化。
ElasticSearch名詞
集群(cluster)
一個集群由一個或多個共享相同的群集名稱的節點組成。每個群集有一個單獨的主節點,這是由程序自動選擇,如果當前主節點失敗,程序會自動選擇其他節點作為主節點。
節點(node)
一個節點屬於一個集群。通常情況下一個服務器有一個節點,但有時候為了測試方便,一台服務器也可以有多個節點。在啟動時,一個節點將使用廣播來發現具有相同群集名稱的現有群集,並將嘗試加入該群集。節點屬性根據elasticsearch.yml的一些配置來決定!其中master和datanode是必不可少的,其他的可以按照情況來進行添加!為了防止腦裂以及后續維護,建議將節點屬性分離!
elasticsearch.yml配置:
-
node.master: true 並且 node.data: true
這種組合表示這個節點即有成為主節點的資格,又存儲數據。
如果某個節點被選舉成為了真正的主節點,那么他還要存儲數據,這樣對於這個節點的壓力就比較大了。ElasticSearch默認每個節點都是這樣的配置,在測試環境下這樣做沒問題。實際工作中建議不要這樣設置,因為這樣相當於主節點和數據節點的角色混合到一塊了。 -
node.master: false 並且 node.data: true
這種組合表示這個節點沒有成為主節點的資格,也就不參與選舉,只會存儲數據。 這個節點我們稱為data(數據)節點。在集群中需要單獨設置幾個這樣的節點負責存儲數據,后期提供存儲和查詢服務。 -
node.master: true 並且 node.data: false
這種組合表示這個節點不會存儲數據,有成為主節點的資格,可以參與選舉,有可能成為真正的主節點,這個節點我們稱為master節點。 -
node.master: false node.data: false
這種組合表示這個節點即不會成為主節點,也不會存儲數據,這個節點的意義是作為一個client(客戶端)節點,主要是針對海量請求的時候可以進行負載均衡。 -
node.ingest: true
執行預處理管道,不負責數據和集群相關的事物。
它在索引之前預處理文檔,攔截文檔的bulk和index請求,然后加以轉換。
將文檔傳回給bulk和index API,用戶可以定義一個管道,指定一系列的預處理器。
示例圖:
上述的節點屬性可以根據實際的情況來進行配置。如果只有三台配置一般的服務器,在測試環境可以將master節點和datanode節點共用,也就是 node.master: true
並且 node.data: true
;在生產環境中,最好將節點分離,特別是masternode和datanode,哪怕是用配置非常差的服務器安裝masternode。至於clientnode則需要看情況,如果有大量的查詢,並且有很多的聚合分析查詢的話,可以部署;ingestnode這個也是看具體的情況,如果有使用ingest等api的情況,也可以進行部署。至於集群規划這個我們在后續的文章中再來講解。
索引(index)
索引是Elasticsearch對邏輯數據的邏輯存儲,所以它可以分為更小的部分。你可以把索引看成關系型數據庫的表。然而,索引的結構是為快速有效的全文索引准備的,特別是它不存儲原始值。如果你知道MongoDB,可以Elasticsearch的索引看成MongoDB里的一個集合。如果你熟悉CouchDB,可以把索引看成CouchDB數據庫索引。Elasticsearch可以把索引存放在一台機器或者分散在多台服務器上,每個索引有一或多個分片(shard),每個分片可以有多個副本(replica)。
根據<ElasticSearch權威指南>將ElasticSearch和傳統關系型數據庫作比較的話如下類比表:
Relational DB -> Databases -> Tables -> Rows -> Columns
Elasticsearch -> Indices -> Types -> Documents -> Fields
但是根據最新的ElasticSearch7.x中已經將Types移除了,並且在日常的使用中,我建議最好把一個索引(index)當做數據庫的一張表來使用,類型(type)除了必要的情況,最好無視它,將它和索引庫名設置一樣即可。
這里順便再來說下創建索引庫的結構。我們知道在關系型數據庫中需要創建表才能添加數據,但是在ElasticSearch中可以直接插入數據,它會根據你的第一條數據來自動創建索引庫的結構, 但是這種在很多情況下是不符合我們要求的。如果我們想自己進行創建的話,那么就有必要了解一下index的setting和mapping了。
setting
setting可以理解為管理這個index的一些重要屬性的,比如分片(shard)和副本(replica),它決定這個索引庫最終的配置形態。初學者的話,可以只用管這三個配置參數即可:
- number_of_shards: 是設置的分片數,設置之后無法更改!
- refresh_interval: 是設置es緩存的刷新時間,如果寫入較為頻繁,但是查詢對實時性要求不那么高的話,可以設置高一些來提升性能。可以更改
- number_of_replicas : 是設置該索引庫的副本數,建議設置為1以上。
mapping
mapping可以理解為關系型數據庫的表結構,指定字段的類型。初學者可以先只用關心text、keyword、byte、short、integer、long、float、double、boolean、date
這幾個字段,其中text和keyword都是string類型,選擇區分很簡單,需要進行分詞用text,不需要並且進行排序或聚合的可以用keyword。
分片(shard)
分片是一個單一的Lucene實例。這個是由Elasticsearch管理的比較底層的功能。索引是指向主分片和副本分片的邏輯空間。對於使用,只需要指定分片的數量,其他不需要做過多的事情。在開發使用的過程中,我們對應的對象都是索引,Elasticsearch會自動管理集群中所有的分片,當發生故障的時候,一個Elasticsearch會把分片移動到不同的節點或者添加新的節點。
-
主分片(primary shard):每個文檔都存儲在一個分片中,當你存儲一個文檔的時候,系統會首先存儲在主分片中,然后會復制到不同的副本中。默認情況下,一個索引有5個主分片。你可以在事先制定分片的數量,當分片一旦建立,分片的數量則不能修改。
-
副本分片(replica shard):每一個分片有零個或多個副本。副本主要是主分片的復制,其中有兩個目的:
1、增加高可用性:當主分片失敗的時候,可以從副本分片中選擇一個作為主分片。
2、提高性能:當查詢的時候可以到主分片或者副本分片中進行查詢。默認情況下,一個主分配有一個副本,但副本的數量可以在后面動態的配置增加。副本必須部署在不同的節點上,不能部署在和主分片相同的節點上。
分片設置很重要!一個index指定了分片之后是無法修改的,因此在設置分片的時候一定要事前做好規划!
示例圖:
文檔
存儲在Elasticsearch中的主要實體叫文檔(document)。用關系型數據庫來類比的話,一個文檔相當於數據庫表中的一行記錄。當比較Elasticsearch中的文檔和MongoDB中的文檔,你會發現兩者都可以有不同的結構,但Elasticsearch的文檔中,相同字段必須有相同類型。這意味着,所有包含 title 字段的文檔, title 字段類型都必須一樣,比如 string 。
文檔由多個字段組成,每個字段可能多次出現在一個文檔里,這樣的字段叫多值字段(multivalued)。每個字段有類型,如文本、數值、日期等。字段類型也可以是復雜類型,一個字段包含其他子文檔或者數組。字段類型在Elasticsearch中很重要,因為它給出了各種操作(如分析或排序)如何被執行的信息。幸好,這可以自動確定,然而,我們仍然建議使用映射。與關系型數據庫不同,文檔不需要有固定的結構,每個文檔可以有不同的字段,此外,在程序開發期間,不必確定有哪些字段。當然,可以用模式強行規定文檔結構。從客戶端的角度看,文檔是一個JSON對象。每個文檔存儲在一個索引中並有一個Elasticsearch自動生成的唯一標識符和文檔類型。文檔需要有對應文檔類型的唯一標識符,這意味着在一個索引中,兩個不同類型的文檔可以有相同的唯一標識符。
- 文檔類型:
在Elasticsearch中,一個索引對象可以存儲很多不同用途的對象。例如,一個博客應用程序可以保存文章和評論。文檔類型讓我們輕易地區分單個索引中的不同對象。每個文檔可以有不同的結構,但在實際部署中,將文件按類型區分對數據操作有很大幫助。當然,需要記住一個限制,不同的文檔類型不能為相同的屬性設置不同的類型。例如,在同一索引中的所有文檔類型中,一個叫 title 的字段必須具有相同的類型。
核心數據類型
text 和 keyword數值數據類型
long,integer,short,byte,double,float,half_float,scaled_float日期數據類型
date布爾數據類型
boolean二進制數據類型
binary范圍數據類型
integer_range,float_range,long_range,double_range,date_range復雜數據類型
對象數據類型
object 用於單個JSON對象嵌套數據類型
nested 用於JSON對象數組地理數據類型
地理位置數據類型
geo_point 緯度/經度積分地理形狀數據類型
geo_shape 用於多邊形等復雜形狀專業數據類型
IP數據類型
ip 用於IPv4和IPv6地址完成數據類型
completion 提供自動完成建議令牌計數數據類型
token_count 計算字符串中令牌的數量
mapper-murmur3
murmur3 在索引時計算值的哈希並將其存儲在索引中
mapper-annotated-text
annotated-text 索引包含特殊標記的文本(通常用於標識命名實體)滲濾器類型
接受來自query-dsl的查詢join 數據類型
為同一索引內的文檔定義父/子關系別名數據類型
為現有字段定義別名。多字段:
為不同的目的以不同的方式對同一字段建立索引通常很有用。例如,一個string字段可以映射為text用於全文搜索的字段,也可以映射為keyword用於排序或聚合的字段。或者,您可以使用standard分析儀, english分析儀和 french分析儀索引文本字段。
這是多領域的目的。大多數數據類型通過fields參數支持多字段。
-
映射:
在有關全文搜索基礎知識部分,我們提到了分析的過程:為建索引和搜索准備輸入文本。文檔中的每個字段都必須根據不同類型做相應的分析。舉例來說,對數值字段和從網頁抓取的文本字段有不同的分析,比如前者的數字不應該按字母順序排序,后者的第一步是忽略HTML標簽,因為它們是無用的信息噪音。Elasticsearch在映射中存儲有關字段的信息。 -
路由(routing):
當存儲一個文檔的時候,他會存儲在一個唯一的主分片中,具體哪個分片是通過散列值的進行選擇。默認情況下,這個值是由文檔的id生成。如果文檔有一個指定的父文檔,從父文檔ID中生成,該值可以在存儲文檔的時候進行修改。
這個屬性在學習初期可以不必理會,使用默認即可。在有一定了解ElasticSearch之后可以在進行了解學習。 -
別名(alias):
它是一個或多個索引的一個附加名稱,允許使用這個名稱來查詢索引。一個別名可以對應多個索引,反之亦然,一個索引可以是多個別名的一部分。別名只能用作查詢,不能進行數據操作!
示例圖:
其它
本文主要介紹了ElasticSearch的一些基礎知識,其中ElasticSearch的理論知識遠遠不止這些,但是介紹的太多的話吸收不過來,其實很多的知識最好是邊學邊用中在掌握。學習ElasticSearch知識理論可以去官網學習,那里有非常詳細的知識。
之后或許會寫一篇關於ElasticSearch的集群規划,會從案例中進行講解,包括機器、節點、索引庫、分片副本一些選擇和配置的一些具體知識。
參考:
https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html
參考書籍:
《ElasticSearch權威指南》
ElasticSearch實戰系列:
ElasticSearch實戰系列一: ElasticSearch集群+Kinaba安裝教程
ElasticSearch實戰系列二: ElasticSearch的DSL語句使用教程---圖文詳解
ElasticSearch實戰系列三: ElasticSearch的JAVA API使用教程
音樂推薦
原創不易,如果感覺不錯,希望給個推薦!您的支持是我寫作的最大動力!
版權聲明:
作者:虛無境
博客園出處:http://www.cnblogs.com/xuwujing
CSDN出處:http://blog.csdn.net/qazwsxpcm
掘金出處:https://juejin.im/user/5ae45d5bf265da0b8a6761e4
個人博客出處:http://www.panchengming.com