首先,我們來看下一下如下的這個圖:
Cluster
Cluster也就是集群的意思。Elasticsearch集群由一個或多個節點組成,可通過其集群名稱進行標識。通常這個Cluster 的名字是可以在Elasticsearch里的配置文件中設置的。在默認的情況下,如我們的Elasticsearch已經開始運行,那么它會自動生成一個叫做“elasticsearch”的集群。我們可以在config/elasticsearch.yml里定制我們的集群的名字
一個Elasticsearch的集群就像是下面的一個布局:
帶有NGINX代理及Balancer的架構圖是這樣的:
可以通過GET _cluster/state
來獲取整個cluster的狀態。這個狀態只能被master node所改變。
node
單個Elasticsearch實例。 在大多數環境中,每個節點都在單獨的盒子或虛擬機上運行。一個集群由一個或多個node組成。在測試的環境中,我可以把多個node運行在一個server上。在實際的部署中,大多數情況還是需要一個server上運行一個node。
根據node的作用,可以分為如下的幾種:
- master-eligible:可以作為主node。一旦成為主node,它可以管理整個cluster的設置及變化:創建,更新,刪除index;添加或刪除node;為node分配shard
- data:數據node
- ingest: 數據接入(比如 pipepline)
- machine learning (Gold/Platinum License)
一般來說,一個node可以具有上面的一種或幾種功能。我們可以在命令行或者Elasticsearch的配置文件(Elasticsearch.yml)來定義:
也可以讓一node做專有的功能及角色。如果上面node配置參數沒有任何配置,那么我們可以認為這個node是作為一個Coordinating node。在這種情況下,它可以接受外部的請求,並轉發到相應的節點來處理。
在實際的使用中,我們可以把請求發送給data節點,而不能發送給master節點。
我們可以通過對elasticsearch.yml文件中配置來定義一個node在集群中的角色:
在有些情況中,我們可以通過設置node.voting_only為true從而使得一個node在node.master為真的情況下,只作為參加voting的功能,而不當選為master node。這種情況為了避免腦裂情況發生。它通常可以使用一個CPU性能較低的node來擔當。
在整個Elastic的架構中,Data Node和Cluster的關系表述如下:
Document
Elasticsearch是面向文檔的,這意味着您索引或搜索的最小數據單元是文檔。文檔在Elasticsearch中有一些重要的屬性:
- 它是獨立的。文檔包含字段(名稱)及其值。
- 它可以是分層的。可以將其視為文檔中的文檔。字段的值可以很簡單,就像位置字段的值可以是字符串一樣。它還可以包含其他字段和值。例如,位置字段可能包含城市和街道地址。
- 結構靈活。您的文檔不依賴於預定義的架構。例如,並非所有事件都需要描述值,因此可以完全省略該字段。但它可能需要新的字段,例如位置的緯度和經度。
文檔通常是數據的JSON表示形式。JSON over HTTP是與Elasticsearch進行通信的最廣泛使用的方式.
很多人認為document相比較於關系數據庫,它相應於其中每個record。
type
類型是文檔的邏輯容器,類似於表是行的容器。 您將具有不同結構(模式)的文檔放在不同類型中。 例如,您可以使用一種類型來定義聚合組,並在人們聚集時為事件定義另一種類型。
每種類型的字段定義稱為映射。 例如,name將映射為字符串,但location下的geolocation字段將映射為特殊的geo_point類型。 (我們探討如何使用附錄A中的地理空間數據。)每種字段的處理方式都不同。 例如,您在名稱字段中搜索單詞,然后按位置搜索組以查找位於您居住地附近的組。
很多人認為Elasticsearch是schemaless的。大家都甚至認為Elasticsearch中的數據庫是不需要mapping的。其實這是一個錯誤的概念。schemaless在Elasticsearch中正確的理解是,我們不需要事先定義一個類型關系數據庫中的table才使用數據庫。在Elasticsearch中,我們可以不開始定義一個mapping,而直接寫入到我們指定的index中。這個index的mapping是動態生成的。其中的數據項的每一個數據類型是動態識別的。比如時間,字符串等,雖然有些的數據類型還是需要我們手動調整,比如geo_point等地理位置數據。另外,它還有一個含義,同一個type,我們在以后的數據輸入中,可能增加新的數據項,從而生產新的mapping。這個也是動態調整的。
由於一些原因,在Elasticsearch 6.0以后,一個Index只能含有一個type。這其中的原因是:相同index的不同映射type中具有相同名稱的字段是相同; 在Elasticsearch索引中,不同映射type中具有相同名稱的字段在Lucene中被同一個字段支持。在默認的情況下是_doc
。在未來8.0的版本中,type將被徹底刪除。
index
在Elasticsearch中,索引是文檔的集合。
每個Index是有一個或許多的documents組成,並且這些document可以分布於不同的shard之中。
很多人認為index類似於關系數據庫中的database。這中說法是有些道理,但是並不完全相同。其中很重要的一個原因是,在Elasticsearch中的文檔可以有object及nested結構。一個index是一個邏輯命名空間,它映射到一個或多個主分片,並且可以具有零個或多個副本分片。
每當一個文檔進來后,根據文檔的id會自動進行hash計算,並存放於計算出來的shard實例中,這樣的結果可以使得所有的shard都比較有均衡的存儲,而不至於有的shard很忙。
shard_num = hash(_routing) % num_primary_shards
在默認的情況下,上面的_routing既是文檔的_id。如果有routing的參與,那么這些文檔可能只存放於一個特定的shard,這樣的好處是對於一些情況,我們可以很快地綜合我們所需要的結果而不需要跨node去得到請求。
從上面的公式我們也可以看出來,我們的shard數目是不可以動態修改的,否則之后也找不到相應的shard號碼了。必須指出的是,replica的數目是可以動態修改的。
shard
由於Elasticsearch是一個分布式搜索引擎,因此索引通常會拆分為分布在多個節點上的稱為分片的元素。 Elasticsearch自動管理這些分片的排列。 它還根據需要重新平衡分片,因此用戶無需擔心細節。
一個索引可以存儲超出單個結點硬件限制的大量數據。比如,一個具有10億文檔的索引占據1TB的磁盤空間,而任一節點都沒有這樣大的磁盤空間;或者單個節點處理搜索請求,響應太慢。
為了解決這個問題,Elasticsearch提供了將索引划分成多份的能力,這些份就叫做分片(shard)。當你創建一個索引的時候,你可以指定你想要的分片(shard)的數量。每個分片本身也是一個功能完善並且獨立的“索引”,這個“索引”可以被放置到集群中的任何節點上。
分片之所以重要,主要有兩方面的原因:
- 允許你水平分割/擴展你的內容容量
- 允許你在分片(潛在地,位於多個節點上)之上進行分布式的、並行的操作,進而提高性能/吞吐量
有兩種類型的分片:primary shard和replica shard。
- Primary shard: 每個文檔都存儲在一個Primary shard。 索引文檔時,它首先在Primary shard上編制索引,然后在此分片的所有副本上(replica)編制索引。索引可以包含一個或多個主分片。 此數字確定索引相對於索引數據大小的可伸縮性。 創建索引后,無法更改索引中的主分片數。
- Replica shard: 每個主分片可以具有零個或多個副本。 副本是主分片的副本,有兩個目的:
- 增加故障轉移:如果主要故障,可以將副本分片提升為主分片
- 提高性能:get和search請求可以由主shard或副本shard處理。
默認情況下,每個主分片都有一個副本,但可以在現有索引上動態更改副本數。 永遠不會在與其主分片相同的節點上啟動副本分片。
下面的圖表示的是一個index有5個shard及1個replica:
可以為每個index設置相應的shard數值:
curl -XPUT http://localhost:9200/another_user?pretty -H 'Content-Type: application/json' -d '
{
"settings" : {
"index.number_of_shards" : 2,
"index.number_of_replicas" : 1
}
}
比如在上面的 REST接口中,我們為another_user這個index設置了2個shards,並且有一個replica。一旦設置好shard的數量,我們就不可以修改了。這是因為Elasticsearch會已經這個數量,會依據每個document的id及shard的數量來把相應的document分配到相應的shard中。如果這個數量以后修改的話,那么每次搜索的時候,可能會找不到相應的shard。
replica
默認情況下,Elasticsearch為每個索引創建一個主分片和一個副本。這意味着每個索引將包含一個主分片,每個分片將具有一個副本。
分配多個分片和副本是分布式搜索功能設計的本質,提供高可用性和快速訪問索引中的文檔。主副本和副本分片之間的主要區別在於只有主分片可以接受索引請求。副本和主分片都可以提供查詢請求。
在上圖中,我們有一個Elasticsearch集群,由默認分片配置中的兩個節點組成。 Elasticsearch自動排列分割在兩個節點上的五個主分片。有一個副本分片對應於每個主分片,但這些副本分片的排列與主分片的排列完全不同。再次,思考分配。
請允許我們澄清一下:請記住,number_of_shards值與索引有關,而不是與整個群集有關。此值指定每個索引的分片數(不是群集中的主分片總數)。
可以通過如下的接口來獲得一個index的健康情況:
http://localhost:9200/_cat/indices/twitter
上面的接口可以返回如下的信息:
http://localhost:9200/_cat/shards
更進一步的查詢,我們可以看出:
如果一個index顯示的是紅色,表面這個index至少有一個primary shard沒有被正確分配,並且有的shard及其相應的replica已經不能正常訪問。
如果是綠色,表明index的每一個shard都有備份,並且其備份也成功復制在相應的replica shard之中。如果其中的一個node壞了,相應的另外一個node的replica或其primary shard將起作用,從而不會造成數據的丟失。
shard 健康:
- 紅色:集群中未分配至少一個主分片
- 黃色:已分配所有主副本,但未分配至少一個副本
- 綠色:分配所有分片