一借浊、Cluster:集群
Elastic Search可以作為一個獨立的單個搜索服務器塘淑。不過,為了處理大型數(shù)據(jù)集蚂斤,實現(xiàn)容錯和高可用性存捺,Elastic Search可以運行在許多互相合作的服務器上,這些服務器形成的整體稱為集群曙蒸。
二捌治、Node:節(jié)點
形成集群的每個服務器稱為節(jié)點
三、Shard:分片
分片纽窟,類似于數(shù)據(jù)庫的分庫操作肖油。當文檔的數(shù)量過大時,由于內(nèi)存的限制师倔、磁盤處理能力不足、無法夠快的響應客戶端的請求等周蹭,一個節(jié)點已經(jīng)不能滿足需求了趋艘,這種情況下,數(shù)據(jù)可以分為較小的分片凶朗,每個分片放到不同的節(jié)點上(說句廢話瓷胧,一般情況下,一個節(jié)點上應該只有一個主分片棚愤,但是一個節(jié)點上不僅只有一個分片搓萧,還可以有很多副本)。
當索引一個文檔的時候宛畦,文檔會被存儲到一個主分片中瘸洛。 那么,Elasticsearch是 如何知道一個文檔應該存放到哪個分片中呢次和?當我們創(chuàng)建文檔時反肋,它如何決定這個文檔應當被存儲在分片 1
還是分片 2
中呢?
首先這肯定不會是隨機的踏施,否則將來要獲取文檔的時候我們就不知道從何處尋找了石蔗。實際上,這個過程是根據(jù)下面這個公式?jīng)Q定的:
shard = hash(routing) % number_of_primary_shards
routing
是一個可變值畅形,默認是文檔的 _id
养距,也可以設置成一個自定義的值。 routing
通過 hash 函數(shù)生成一個數(shù)字日熬,然后這個數(shù)字再除以 number_of_primary_shards
(主分片的數(shù)量)后得到 余數(shù) 棍厌。這個分布在 0
到 number_of_primary_shards-1
之間的余數(shù),就是我們所尋求的文檔所在分片的位置。
這就解釋了為什么我們要在創(chuàng)建索引的時候就確定好主分片的數(shù)量 并且永遠不會改變這個數(shù)量:因為如果數(shù)量變化了定铜,那么所有之前路由的值都會無效阳液,文檔也再也找不到了。
當查詢的索引分布在多個分片上時揣炕,ES會把查詢發(fā)送給每個相關的分片帘皿,并將結果組合在一起,而應用程序并不知道分片的存在畸陡。
分片與路由
因為分布式索引會進行類似于數(shù)據(jù)庫分庫分表的操作鹰溜。假如現(xiàn)在有2個分片,有4篇文檔id分別為:1丁恭,2曹动,3,4牲览,根據(jù)取模算法墓陈,將他們分配到對應的表中。Elastic Search采取的也是這種思路第献。數(shù)據(jù)1和3 對2取模贡必,等于 1,那么就會把1庸毫,3兩個數(shù)據(jù)放到第2個分片上仔拟。2和4對2取模,等于0飒赃,那么就會把2利花,4兩條數(shù)據(jù)放到第1個分片上。
查詢數(shù)據(jù)的時候同理载佳,查詢1炒事,3,根據(jù)取模運算結果蔫慧,會去第2個分片上查找羡洛。查詢2,4藕漱,會去第1個分片上查找欲侮。這個時候,修改了分片數(shù)目肋联,取模運算結果與之前不一致威蕉,比如改成3個分片,那么查詢3的時候橄仍,取模運算結果變成了0韧涨,就會去第1個分片上查找3牍戚,那么肯定查不到的。因此分片數(shù)不能隨意修改虑粥,一旦修改如孝,需要全部重建索引。
四娩贷、Replica:副本
Elastic Search中可以有許多相同的分片第晰,其中之一可以進行編輯操作(如增刪改),這種特殊的分片稱為主分片彬祖。而副本是一個分片的精確復制茁瘦,每個分片可以有零個或多個副本。
當主分片丟失時储笑,如:該分片所在的數(shù)據(jù)不可用時甜熔,集群將副本提升為新的主分片。
number_of_replicas
副本數(shù)突倍,用于備份分片的腔稀,和分片里面的數(shù)據(jù)保持一致,主要響應讀操作羽历,副本越多讀取就越快焊虏。此外,副本數(shù)是可以修改的窄陡。但是在集群環(huán)境中炕淮,副本數(shù)應小于等于節(jié)點數(shù)減1拆火,否則會降低集群的健康值跳夭。
我們前面說,一個節(jié)點應該只有一個主分片们镜。但是實際中币叹,我們需要預估一下將來的分片數(shù),并且提前做規(guī)劃模狭。在《Elastic Search權威指南》中颈抚,提到了擴容設計。其中指出嚼鹉,在初期贩汉,我們可以只有一個節(jié)點,并且可以在該節(jié)點中建立多個主分片锚赤。當訪問量增加匹舞,節(jié)點負荷過大時,我們可以增加新的節(jié)點线脚,更加奇妙的是Elasticsearch 會自動將其中部分分片移動至到新的節(jié)點赐稽。就如下圖所示
引自:https://www.elastic.co/guide/cn/elasticsearch/guide/current/overallocation.html
此外叫榕,新的版本的副本復制策略同6.6不太一樣,具體可以參考http://www.reibang.com/p/a164b86445b6
五姊舵、文檔晰绎,元數(shù)據(jù)
1,文檔
在大多數(shù)應用中括丁,多數(shù)實體或對象可以被序列化為包含鍵值對的 JSON 對象荞下。 一個 鍵 可以是一個字段或字段的名稱,一個 值 可以是一個字符串躏将,一個數(shù)字锄弱,一個布爾值, 另一個對象祸憋,一些數(shù)組值会宪,或一些其它特殊類型諸如表示日期的字符串,或代表一個地理位置的對象
2蚯窥,文檔元數(shù)據(jù)
一個文檔不僅僅包含它的數(shù)據(jù) 掸鹅,也包含 元數(shù)據(jù) —— 有關 文檔的信息。 三個必須的元數(shù)據(jù)元素如下:
-
_index
文檔在哪存放
一個 索引 應該是因共同的特性被分組到一起的文檔集合拦赠。 例如巍沙,你可能存儲所有的產(chǎn)品在索引
products
中,而存儲所有銷售的交易到索引sales
中荷鼠。 雖然也允許存儲不相關的數(shù)據(jù)到一個索引中句携,但這通常看作是一個反模式的做法允乐。實際上矮嫉,在 Elasticsearch 中,我們的數(shù)據(jù)是被存儲和索引在 分片 中牍疏,而一個索引僅僅是邏輯上的命名空間蠢笋, 這個命名空間由一個或者多個分片組合在一起。 然而鳞陨,這是一個內(nèi)部細節(jié)昨寞,我們的應用程序根本不應該關心分片,對于應用程序而言厦滤,只需知道文檔位于一個 索引 內(nèi)援岩。 Elasticsearch 會處理所有的細節(jié)。
-
_type
文檔表示的對象類別
數(shù)據(jù)可能在索引中只是松散的組合在一起掏导,但是通常明確定義一些數(shù)據(jù)中的子分區(qū)是很有用的享怀。 例如,所有的產(chǎn)品都放在一個索引中碘菜,但是你有許多不同的產(chǎn)品類別凹蜈,比如 "electronics" 限寞、 "kitchen" 和 "lawn-care"。
需要注意的是仰坦,Elastic Search 6之后履植,_type 只有一個,而到了Elastic Search 7 之后悄晃,取消了 _type玫霎。
為什么 _type 被移除了?
起初妈橄,我們說"索引"和關系數(shù)據(jù)庫的“庫”是相似的庶近,“類型”和“表”是對等的。這是一個不正確的對比眷蚓,導致了不正確的假設鼻种。在關系型數(shù)據(jù)庫里,"表"是相互獨立的,一個“表”里的列和另外一個“表”的同名列沒有關系沙热,互不影響叉钥。但在類型里字段不是這樣的。在一個Elasticsearch索引里篙贸,所有不同類型的同名字段內(nèi)部使用的是同一個lucene字段存儲投队。也就是說,上面例子中爵川,user類型的user_name字段和tweet類型的user_name字段是存儲在一個字段里的敷鸦,兩個類型里的user_name必須有一樣的字段定義。這可能導致一些問題寝贡,例如你希望同一個索引中"deleted"字段在一個類型里是存儲日期值扒披,在另外一個類型里存儲布爾值。最后,在同一個索引中兔甘,存儲僅有小部分字段相同或者全部字段都不相同的文檔谎碍,會導致數(shù)據(jù)稀疏鳞滨,影響Lucene有效壓縮數(shù)據(jù)的能力洞焙。因為這些原因,我們決定從Elasticsearch中移除類型的概念拯啦。
-
_id
文檔唯一標識
ID 是一個字符串澡匪,當它和
_index
以及_type
組合就可以唯一確定 Elasticsearch 中的一個文檔。 當你創(chuàng)建一個新的文檔褒链,要么提供自己的_id
唁情,要么讓 Elasticsearch 幫你生成。當Elastic Search7 取消
_type
之后甫匹,及_index
和_id
即可確定唯一的文檔甸鸟。
五惦费、文檔,元數(shù)據(jù)
1抢韭,文檔
在大多數(shù)應用中薪贫,多數(shù)實體或對象可以被序列化為包含鍵值對的 JSON 對象。 一個 鍵 可以是一個字段或字段的名稱刻恭,一個 值 可以是一個字符串瞧省,一個數(shù)字,一個布爾值鳍贾, 另一個對象鞍匾,一些數(shù)組值,或一些其它特殊類型諸如表示日期的字符串骑科,或代表一個地理位置的對象
2橡淑,文檔元數(shù)據(jù)
一個文檔不僅僅包含它的數(shù)據(jù) ,也包含 元數(shù)據(jù) —— 有關 文檔的信息咆爽。 三個必須的元數(shù)據(jù)元素如下:
-
_index
文檔在哪存放
一個 索引 應該是因共同的特性被分組到一起的文檔集合梳码。 例如,你可能存儲所有的產(chǎn)品在索引
products
中伍掀,而存儲所有銷售的交易到索引sales
中掰茶。 雖然也允許存儲不相關的數(shù)據(jù)到一個索引中,但這通趁垠裕看作是一個反模式的做法濒蒋。實際上,在 Elasticsearch 中把兔,我們的數(shù)據(jù)是被存儲和索引在 分片 中沪伙,而一個索引僅僅是邏輯上的命名空間, 這個命名空間由一個或者多個分片組合在一起县好。 然而围橡,這是一個內(nèi)部細節(jié),我們的應用程序根本不應該關心分片缕贡,對于應用程序而言翁授,只需知道文檔位于一個 索引 內(nèi)。 Elasticsearch 會處理所有的細節(jié)晾咪。
-
_type
文檔表示的對象類別
數(shù)據(jù)可能在索引中只是松散的組合在一起收擦,但是通常明確定義一些數(shù)據(jù)中的子分區(qū)是很有用的。 例如谍倦,所有的產(chǎn)品都放在一個索引中塞赂,但是你有許多不同的產(chǎn)品類別,比如 "electronics" 昼蛀、 "kitchen" 和 "lawn-care"宴猾。
需要注意的是圆存,Elastic Search 6之后,_type 只有一個仇哆,而到了Elastic Search 7 之后辽剧,取消了 _type。
為什么 _type 被移除了税产?
起初怕轿,我們說"索引"和關系數(shù)據(jù)庫的“庫”是相似的,“類型”和“表”是對等的辟拷。這是一個不正確的對比撞羽,導致了不正確的假設。在關系型數(shù)據(jù)庫里,"表"是相互獨立的衫冻,一個“表”里的列和另外一個“表”的同名列沒有關系诀紊,互不影響。但在類型里字段不是這樣的隅俘。在一個Elasticsearch索引里邻奠,所有不同類型的同名字段內(nèi)部使用的是同一個lucene字段存儲。也就是說为居,上面例子中碌宴,user類型的user_name字段和tweet類型的user_name字段是存儲在一個字段里的,兩個類型里的user_name必須有一樣的字段定義蒙畴。這可能導致一些問題贰镣,例如你希望同一個索引中"deleted"字段在一個類型里是存儲日期值,在另外一個類型里存儲布爾值膳凝。最后,在同一個索引中碑隆,存儲僅有小部分字段相同或者全部字段都不相同的文檔,會導致數(shù)據(jù)稀疏蹬音,影響Lucene有效壓縮數(shù)據(jù)的能力上煤。因為這些原因,我們決定從Elasticsearch中移除類型的概念著淆。
-
_id
文檔唯一標識
ID 是一個字符串劫狠,當它和
_index
以及_type
組合就可以唯一確定 Elasticsearch 中的一個文檔。 當你創(chuàng)建一個新的文檔牧抽,要么提供自己的_id
嘉熊,要么讓 Elasticsearch 幫你生成遥赚。當Elastic Search7 取消
_type
之后扬舒,及_index
和_id
即可確定唯一的文檔。
六凫佛、新建讲坎,索引孕惜,刪除操作的基本邏輯
假設我們?nèi)缟厦嫠荆厦婷總€節(jié)點都可以接收寫請求晨炕,那么新增數(shù)據(jù)的一個流程如下所示:
步驟順序如下:
(1) 客戶端向Node1發(fā)送新建請求(如果客戶端向Node2或者Node3等其他節(jié)點發(fā)送請求衫画,請求會被轉發(fā)給Master節(jié)點,本圖中為Node1瓮栗,更新削罩,刪除同理)。
(2) master根據(jù)_id確定文檔屬于分片0费奸,那么請求會被轉發(fā)到Node3弥激,因為分片 0 的主分片目前被分配在 Node3上。
(3) Node 3在主分片上面執(zhí)行請求愿阐。如果成功了微服,它將請求并行轉發(fā)到 Node 1和 Node 2 的副本分片上。一旦所有的副本分片都報告成功, Node3 將向Master節(jié)點報告成功缨历,Master節(jié)點向客戶端報告成功(ES新版本是可用shard寫入成功過半以蕴,Node3會發(fā)送消息給master,并由Master節(jié)點轉發(fā)給請求來源節(jié)點)辛孵。
在客戶端收到成功響應時丛肮,文檔變更已經(jīng)在主分片和所有副本分片執(zhí)行完成,變更是安全的魄缚。
七腾供、查詢的基本邏輯
以下是從主分片或者副本分片檢索文檔的步驟順序:
1、客戶端向 Node 1
發(fā)送獲取請求鲜滩。
2伴鳖、節(jié)點使用文檔的 _id
來確定文檔屬于分片 0
。分片 0
的副本分片存在于所有的三個節(jié)點上徙硅。 在這種情況下榜聂,它將請求轉發(fā)到 Node 2
。在處理讀取請求時嗓蘑,Master節(jié)點在每次請求的時候都會通過輪詢所有的副本分片來達到負載均衡须肆,因此會轉發(fā)請求到Node 2
。
3桩皿、Node 2
將文檔返回給 Node 1
豌汇,然后將文檔返回給客戶端。
在文檔被檢索時泄隔,已經(jīng)被索引的文檔可能已經(jīng)存在于主分片上但是還沒有復制到副本分片拒贱。 在這種情況下,副本分片可能會報告文檔不存在,但是主分片可能成功返回文檔逻澳。 一旦索引請求成功返回給用戶闸天,文檔在主分片和副本分片都是可用的。