目錄
一 叢集
二 索引
三 文檔
3.1 文檔的定義
3.2 文檔中繼資料
hits
took
shards
timeout
3.3 文檔、索引、叢集關系
四 分片
4.1 分片、文檔、叢集關系?
4.2 複制分片作用?
4.3 文檔是如何路由的?
五 叢集健康
六 分頁
6.1 在分布式系統中深度分頁
一 叢集
一個 Elasticsearch 叢集由一個或多個節點(Node)組成,每個叢集都有一個共同的叢集名稱作為辨別。
二 索引
索引是一系列相同格式文檔的集合。索引實際上是指向一個或者多個實體分片的邏輯命名空間。
索引在 Elasticsearch 語境中有多種含義:
- 索引(名詞):
如前所述,一個索引類似于傳統關系資料庫中的一個資料庫 ,是一個存儲關系型文檔的地方。 索引 (index) 的複數詞為 indices 或 indexes 。
- 索引(動詞):
索引一個文檔,就是存儲一個文檔到一個索引(名詞)中以便被檢索和查詢。這非常類似于 SQL 語句中的 INSERT 關鍵詞,除了文檔已存在時,新文檔會替換舊文檔情況之外。
- 反向索引:
關系型資料庫通過增加一個索引,比如一個 B樹(B-tree)索引 到指定的列上,以便提升資料檢索速度。Elasticsearch 和 Lucene 使用了一個叫做反向索引的結構來達到相同的目的。
三 文檔
3.1 文檔的定義
它是指最頂層或者根對象, 這個根對象被序列化成 JSON 并存儲到 Elasticsearch 中,指定了唯一 ID。
3.2 文檔中繼資料
一個文檔不僅僅包含它的資料 ,也包含中繼資料 —— 有關文檔的資訊。 三個必須的中繼資料元素如下:
-
:文檔在哪存放。_index
-
:文檔表示的對象類别。_type
-
:文檔唯一辨別。_id
3.2.1
_index
一個索引應該是因共同的特性被分組到一起的文檔集合。
一個 _index 索引名字必須小寫,不能以下劃線開頭,不能包含逗号。
3.2.2
_type
資料可能在索引中隻是松散的組合在一起,但是通常明确定義一些資料中的子分區是很有用的。
例如,所有的産品都放在一個索引中,但是你有許多不同的産品類别,比如 "electronics" 、 "kitchen" 和 "lawn-care"。
這些文檔共享一種相同的(或非常相似)的模式:他們有一個标題、描述、産品代碼和價格。他們隻是正好屬于“産品”下的一些子類。
Elasticsearch 公開了一個稱為 types (類型)的特性,它允許您在索引中對資料進行邏輯分區。
一個
_type
命名可以是大寫或者小寫,但是不能以下劃線或者句号開頭,不應該包含逗号, 并且長度限制為256個字元。
3.2.3
_id
ID 是一個字元串,當它和
_index
以及
_type
組合就可以唯一确定 Elasticsearch 中的一個文檔。 當你建立一個新的文檔,要麼提供自己的
_id
,要麼讓 Elasticsearch 幫你生成。
3.2.4 hits
{
"hits" : {
"total" : 14,
"hits" : [
{
"_index": "us",
"_type": "tweet",
"_id": "7",
"_score": 1,
"_source": {
"date": "2014-09-17",
"name": "John Smith",
"tweet": "The Query DSL is really powerful and flexible",
"user_id": 2
}
},
... 9 RESULTS REMOVED ...
],
"max_score" : 1
},
"took" : 4,
"_shards" : {
"failed" : 0,
"successful" : 10,
"total" : 10
},
"timed_out" : false
}
hits
傳回結果中最重要的部分是
hits
,它包含
total
字段來表示比對到的文檔總數,并且一個
hits
數組包含所查詢結果的前十個文檔。
在
hits
數組中每個結果包含文檔的
_index
、
_type
、
_id
,加上
_source
字段。這意味着我們可以直接從傳回的搜尋結果中使用整個文檔。這不像其他的搜尋引擎,僅僅傳回文檔的ID,需要你單獨去擷取文檔。
每個結果還有一個
_score
,它衡量了文檔與查詢的比對程度。預設情況下,首先傳回最相關的文檔結果,就是說,傳回的文檔是按照
_score
降序排列的。在這個例子中,我們沒有指定任何查詢,故所有的文檔具有相同的相關性,是以對所有的結果而言
1
是中性的
_score
。
max_score
值是與查詢所比對文檔的
_score
的最大值。
took
took
值告訴我們執行整個搜尋請求耗費了多少毫秒。
shards
_shards
部分告訴我們在查詢中參與分片的總數,以及這些分片成功了多少個失敗了多少個。正常情況下我們不希望分片失敗,但是分片失敗是可能發生的。如果我們遭遇到一種災難級别的故障,在這個故障中丢失了相同分片的原始資料和副本,那麼對這個分片将沒有可用副本來對搜尋請求作出響應。假若這樣,Elasticsearch 将報告這個分片是失敗的,但是會繼續傳回剩餘分片的結果。
timeout
timed_out
值告訴我們查詢是否逾時。預設情況下,搜尋請求不會逾時。如果低響應時間比完成結果更重要,你可以指定
timeout
為 10 或者 10ms(10毫秒),或者 1s(1秒):
應當注意的是
timeout
不是停止執行查詢,它僅僅是告知正在協調的節點傳回到目前為止收集的結果并且關閉連接配接。在背景,其他的分片可能仍在執行查詢即使是結果已經被發送了。
使用逾時是因為 SLA(服務等級協定)對你是很重要的,而不是因為想去中止長時間運作的查詢。
3.3 文檔、索引、叢集關系
- 每個 Elasticsearch 叢集可以包含多個索引。
- 每個索引可以包含多個類型 (Elasticsearch 6.x 已不支援一個索引下多個Type)。
- 每個類型存儲着多個文檔。
- 每個文檔又有多個屬性。
四 分片
- 一個分片是一個底層的工作單元 ,它僅儲存了全部資料中的一部分。
- 分片可分為主分片( primary shard)和複制分片(replica shard),複制分片是主分片的拷貝。
- 索引内任意一個文檔都歸屬于一個主分片,是以主分片的數目決定着索引能夠儲存的最大資料量。
技術上來說,一個主分片最大能夠存儲 Integer.MAX_VALUE - 128 個文檔,但是實際最大值還需要參考你的使用場景:
包括你使用的硬體, 文檔的大小和複雜程度,索引和查詢文檔的方式以及你期望的響應時長。
- 預設每個主分片有一個複制分片(預設一個索引建立後會有5個主分片,即:5主+5複制=10個分片),
- 一個索引的複制分片的數量可以動态地調整,複制分片從不與它的主分片在同一個節點上(防止單點故障)。
4.1 分片、文檔、叢集關系?
- 分片是資料的容器。
- 文檔儲存在分片内。
- 分片又被配置設定到叢集内的各個節點裡。
4.2 複制分片作用?
- 提高恢複能力:當主分片挂掉時,某個複制分片可以變成主分片。
- 提高性能:get 和 search 請求既可以由主分片又可以由複制分片處理。
4.3 文檔是如何路由的?
當索引一個文檔的時候,文檔會被存儲到一個主分片中。 Elasticsearch 如何知道一個文檔應該存放到哪個分片中呢?當我們建立文檔時,它如何決定這個文檔應當被存儲在分片
1
還是分片
2
中呢?
首先這肯定不會是随機的,否則将來要擷取文檔的時候我們就不知道從何處尋找了。實際上,這個過程是根據下面這個公式決定的:
shard = hash(routing) % number_of_primary_shards
-
是一個可變值,預設是文檔的routing
,也可以設定成一個自定義的值。_id
-
通過 hash 函數生成一個數字,然後這個數字再除以routing
(主分片的數量)後得到餘數 。number_of_primary_shards
- 這個分布在 到
之間的餘數,就是我們所尋求的文檔所在分片的位置。number_of_primary_shards-1
這就解釋了為什麼我們要在建立索引的時候就确定好主分片的數量,并且永遠不會改變這個數量:因為如果數量變化了,那麼所有之前路由的值都會無效,文檔也再也找不到了。
五 叢集健康
- green
所有的主分片和副本分片都正常運作。
- yellow
所有的主分片都正常運作,但不是所有的副本分片都正常運作。
- red
有主分片沒能正常運作。
六 分頁
和 SQL 使用
LIMIT
關鍵字傳回單個
page
結果的方法相同,Elasticsearch 接受
from
和
size
參數:
size
:顯示應該傳回的結果數量,預設是
10。
from
:顯示應該跳過的初始結果數量,預設是
0。
6.1 在分布式系統中深度分頁
了解為什麼深度分頁是有問題的,我們可以假設在一個有 5 個主分片的索引中搜尋。 當我們請求結果的第一頁(結果從 1 到 10 ),每一個分片産生前 10 的結果,并且傳回給 協調節點 ,協調節點對 50 個結果排序得到全部結果的前 10 個。
現在假設我們請求第 1000 頁—結果從 10001 到 10010 。所有都以相同的方式工作除了每個分片不得不産生前10010個結果以外。 然後協調節點對全部 50050 個結果排序最後丢棄掉這些結果中的 50040 個結果。
可以看到,在分布式系統中,對結果排序的成本随分頁的深度成指數上升。這就是 web 搜尋引擎對任何查詢都不要傳回超過 1000 個結果的原因。