#Elasticsearch分佈式的操做node
咱們知道在建立索引的時候咱們時能夠決定建立多少個主分片(只能建立的時候指定,之後不可修改)和多少個複製分片(副分片,建立的時候能夠改變,以後也能夠改變)。Elasticsearch有這個規定其實是爲了剪碎文檔,它檢索文檔是基於一個簡單的算法來決定的算法
shard=hash(routing)%number_of_primary_shards
複製代碼
這裏的routing是一個任意的字符串,默認是_id,它是能夠自定義的。這個routing字符串經過哈希函數生產一個數字,而後初一主分片的數量獲得一個餘數(remainder),餘數的範圍永遠是0到number_of)shards-1,這個數字就是特定文檔的所在的分片(也就是解釋了爲何主分片在建立以後不能該的緣由)數組
咱們的請求到節點的任意一個接待你,每一個節點都有能力來處理請求。每一個節點都知道任意文檔所在的節點,索引也能夠將請求轉發到須要的節點,這個節點也稱爲請求節點。網絡
文檔的建立,索引和刪除請求都是寫操做,它們都必須在主分片上完成功能才能複製到相關和的複製分片上。數據結構
它的步驟以下:async
1.客戶端給Node1發送建立,索引或者刪除請求。分佈式
2.節點使用文檔的_id肯定文檔屬於分片0,它轉發請求到Node3,分片位於該節點上。函數
3.Node3在主分片上執行請求,若是成功,它轉發請求到相應的位於Node1和Node2的複製節點上。若是Node3報告成功到請求的節點,請求節點在報告給客戶端。spa
客戶端在收到請求的響應的時候就已經修改爲功,主分片和複製分片都已經被應用了。3d
複製默認的值是sync。這將致使主分片獲得的複製分的成功響應才返回。若是將複製節點設置成async,請求在主分片上執行後就會返回客戶端。請求依舊轉發到複製節點,可是複製節點成功與否咱們不得而知。
默認主分片在寫入時須要規定數量(quorum)或者過半的分片(可使主節點或者複製分片)可用。這是防止數據被寫入到錯的網絡分區
int((primary+number_of_replicas)/2)+1
複製代碼
consistency值 | 意義 |
---|---|
one | 只有一個主分片 |
all | 全部主分片和複製分片 |
quorum | 規定數量 |
例子:
若是隻有兩個節點,給索引定義了三個複製節點,那麼咱們規定的數據量就是int((primary+3replicas)/2)+1=3,若是活動分片不夠沒那麼就不可以索引或者刪除任何文檔。
當分片副本不足時會怎麼樣?Elasticsearch會等待更多的分片出現,默認是1分鐘,若是須要,你能夠設置timeout參數種植的更早,例如100表示100毫秒,100s表示100秒。
注意:新索引默認只有一個複製分片,可是這樣沒法知足quorum的要求須要兩個而得到的分片。固然,這個默認設置將組織咱們在單一節點集羣中進行操做。Wie了避開這個問題,規定只有數量在number_of_replicas大於1時才生效。
主分片和複製分片上檢索一個文檔必要的順序步驟:
1.客戶端給節點1發送請求(get) 2.節點使用文檔的_id肯定文檔屬於分片0.分片0對應的複製負片分別在三個節點上。此時就會妝發請求給節點2. 3.節點2返回文檔給節點1而後返回給客戶端。
##局部更新文檔
局部修改文檔通常須要主節點來完成,而後同步數據到其餘的複製節點。
以下例子所示:
1.客戶端給Node1發送修改請求
2.轉發請求到主分片所在node3
3.node3從主分片檢索出文檔,修改_source字段的JSON,而後在主分片上重建索引。若是有其餘的進程修改了文檔,它以retry_on_conflict設置的次數重複步驟3,都爲成功則放棄。
4.若是node3成功則文檔更新成功,它同時轉發文檔的新版本到node1和node2上的複製分片重建索引。當複製節點報告成功,Node3就返回成功給請求節點,而後返回給客戶端。
mget和bulk API與單獨的文檔也是相似的,差異的地方是在於,它把多文檔七八個球拆成每一個分片的對文檔氫氣與,而後轉發請求。一旦接受每一個節點對應的答應,而後整理這些響應組合爲一個單獨的響應返回給客戶端。
mget請求的步驟
bulk操做的步驟 1.客戶端向Node1發送bulk請求 2.Node1爲每一個分片構建批量請求,而後轉發到這些請求所須要的主分片上。 3.住分片一個接一個的按順序執行操做。當一個操做執行完,住分片轉發新文檔(或者刪除部分)給對應的複製節點,而後執行下一個操做。一旦全部的複製節點報告全部的操做成功完成,節點就報告success給請求接待你,後者(請求節點)整理響應並返回給客戶端。
bulk操做不一樣於其餘操做,不能直接使用JSON做爲請求體,由於批量操做每一個引用屬於不一樣的主分片,每一個分片可能被分佈於集羣中的某個節點上。這意味這批量操做都要被妝發到對應的分片和節點上。若是單獨的請求被包裝到JSON數組中,那一位着咱們須要:
1.解析JSON爲數組(包括文檔數組,可能很是大)
2.檢查每一個請求決定應該到哪一個分片上
3.爲每一個分片建立一個請求的數組
4.序列化這些數組爲內部傳輸格式
5.發送請求到每一個分片
這可行,但須要大量的RAM來承載本質上相同的數據,還要建立更多的數據結構使得JVM花更多的時間執行垃圾回收。取而代之的,Elasticsearch則是從網絡緩衝區中一行一行的直接讀取數據。它使用換行符識別和解析action/metadata行,以決定哪些分片來處理這個請求。這些行請求直接轉發到對應的分片上。這些沒有冗餘複製,沒有多餘的數據結構。整個請求過程使用最小的內存在進行。
和SQL同樣使用LIMIT分頁,Elasticsearch接受from和size參數做爲分頁的關鍵字: size:結果數,默認是10, from:跳過開始的結果數,默認是0.
注意:
應該注意分頁太深或者一次請求太多的結果。結果在返回以前會被排序。可是記住一個請求請求經常涉及不少分片。每一個分片生產本身排好序的結果,他們接着須要集中起來拍尋以確保總體排序正確。(例如:若是咱們有5個分片,每一個分片返回10條結果,5個分片就會返回50條結果,而後在獲取總體的10條結果,這就也就是爲何深度分頁須要花費更多計算和內存)
Elasticsearch有兩種表單:
1.一種是"簡易版"的查詢字符串(query string) 將全部參數經過查詢字符串定義。
GET /test/_doc/_search?q=field1:value3
複製代碼
2.使用JSON完整的表示請求體,這種富搜索語言叫作結構化查詢語句(DSL)
GET /test/_doc/_search
{
"query":{
"match":{
"field1":"value3"
}
}
}
複製代碼