elasticsearch 增刪改查底層原理

elasticsearch專欄:https://www.cnblogs.com/hello-shf/category/1550315.htmlhtml

1、預備知識

在對document的curd進行深度分析以前,咱們不得不瞭解如下幾個小的知識點,不瞭解一下幾個知識點咱們將很難理解document是如何進行增刪改查的。node

 

1.一、路由(索引)與primary shard不可變

你們有沒有考慮過這個問題,當你索引一個文檔,它被存儲在單獨一個主分片上。Elasticsearch是如何知道文檔屬於哪一個分片的呢?當你建立一個新文檔,它是如何知道是應該存儲在分片1仍是分片2上的呢? 進程不能是隨機的,由於咱們未來要檢索文檔。事實上,它根據一個簡單的算法決定:算法

shard = hash(routing) % number_of_primary_shards 

routing值是一個任意字符串,它默認是 _id 但也能夠自定義。這個 routing 字符串經過哈 希函數生成一個數字,而後除以主切片的數量獲得一個餘數(remainder),餘數的範圍永遠 是 0 到 number_of_primary_shards - 1 ,這個數字就是特定文檔所在的分片。負載均衡

這也解釋了爲何主分片的數量只能在建立索引時定義且不能修改:若是主分片的數量在將來改變了,全部先前的路由值就失效了,文檔也就永遠找不到了。async

咱們演示一下這個路由的過程。假設咱們有三個節點,一個student索引,對應有三個primary shard和一個replica shard。此時集羣如圖1所示elasticsearch

向該節點中插入一個document,而且咱們指定_id(在es中_id能夠自定義es也能夠自動生成)假如_id = 1000,根據咱們上面描述,此時會按照以下算法計算其會命中哪一個shard。假設此時hash(1000)= 13;函數

shard = hash(routing) % number_of_primary_shards
即:
shard = 13 % 3 = 1;(假設hash(1000) = 13)
注:由於es的hash函數具體是怎麼計算的不得而知,也不重要,咱們主要是關注其原理。

 根據計算可得該插入請求會命中P1,shard此時會將該document插入到P1。是否是很簡單。性能

以上也可就是es路由的過程,也可稱爲es索引(這個索引是動詞,理解一下)過程。spa

 

1.二、shard負載均衡與節點對等

在es集羣中每一個節點,每一個shard(包括primary shard和replica shard)都具有處理任何請求的能力。這意味着在es集羣中節點間是高度的負載均衡的,即並非只有主節點是流量的入口,每一個節點都具有處理請求的能力。primary shard和replica shard也是高度負載均衡的,由於並非只有primary shard才具有處理curd的能力,replica shard可處理檢索的請求。這也是es的性能爲何表現這麼好的緣由之一。code

 

2、document增、刪、改

2.一、增刪改過程分析

新建、索引和刪除請求都是寫(write)操做,它們必須在primary shard上成功完成才能複製到相關的replica shard分片上。

關於新增document索引過程能夠參考《es的索引過程》

 

 

 

 如上圖所示,從客戶端發起請求到es集羣向客戶端響應大體能夠分爲以上6個階段。

階段1:

  客戶端向node1發起增、刪、改請請求。node1將做爲協調節點(coordinate node)進行相關工做。

階段2:

  node1根據文檔 _id 計算出命中的primary shard爲P1,而後將請求轉發到node2,P1分片位於node2上面。

階段3:

  node2在P1上處理該請求。若是請求處理成功,node2將會把請求繼續轉發到其副本R1上。R1位於node3。

階段4:

  node3在R1上處理完該請求,若是成功,node3會將處理成功的消息返回給node2。

階段5:

  node2收到P1副本處理成功的消息,也就意味着該請求已經處理完成。而後將處理結果返回給node1節點。

階段6:

  協調節點node1收到響應結果後,將該結果返回給客戶端。

整個過程就完成了。

看到這裏你們是否是也在思考一個請求進來,我還要等待全部的分片都處理完成這個操做纔算是完成,這樣是否是很影響響應速度。基於這個思考,es一樣也給咱們提供了自定義參數的支持,好比咱們可使用replication參數來指定primary shard是否是要等到replica shard處理完成後才能響應到客戶端。可是,該配置配置參數並不推薦使用,你們知道有這麼個東西就好了。

replication:默認值爲  sync  該值意味着primary shard須要等到其全部的副本分片都完成後纔會響應客戶端。若是咱們將該值設置爲  async ,意味着primary shard完成後就會返回給客戶端,可是並不意味着其不會將請求轉發到副本上,主分片依然會將請求轉發到replica shard上,只不過咱們再也不肯定副本是否是也完成了該請求,這樣將不能保證數據的一致性。
 

2.一、寫一致性保障

首先須要說明的一點,增刪改其實都是一個寫操做,因此這裏的寫指的是增刪改三個操做。
這裏咱們所說的寫一致性指的是primary shard和replica shard上數據的一致性。es API爲咱們提供了一個可自定的參數consistency。該參數可讓咱們自定義處理一次增刪改請求,是否是必需要求全部分片都是active的纔會執行。
該參數可選的值有三個:one,all,quorum(default,默認)。
1 one:要求咱們這個寫操做,只要有一個primary shard是active活躍可用的,就能夠執行。
2 all:要求咱們這個寫操做,必須全部的primary shard和replica shard都是活躍的,才能夠執行這個寫操做
3 quorum:默認的值,要求全部的shard中,必須是大部分的shard都是活躍的,可用的,才能夠執行這個寫操做

 上面三點其實很好理解,只有quorum所謂的「大部分」感受不是那麼的明確。下面有個公式,當集羣中的active(可用)分片數量達到以下公式結果時寫操做就是能夠執行的。不然該操做將沒法進行。

int( (primary + number_of_replicas) / 2 ) + 1

依然用咱們上面的例子,假設咱們建立了一個student索引,而且設置primary shard爲3個,replica shard有1個(這個1個是相對於索引來講的,對於主分片該數字1意味着每一個primary shard都對應的存在一個副本)。也就意味着primary=3,number_of_replicas=1(依然是相對於索引)。shard總數爲6。

此時計算上面公式可知:

int((3+1)/2) + 1 = 3
也就是說當集羣中可用的shard數量>=3寫操做就是能夠執行的。
說了這麼多好像還沒解釋以上跟寫一致性有什麼關係。es對寫一致性的保證就是經過quorum來保證的,覺得quorum要求es集羣中的可用shard數量達到必定要求才能執行。也就間接保證了shard的數據一致性。
具體使用也很簡單
PUT /index/type/id?consistency=quorum

 固然若是咱們不指定就是使用默認的,也就是quorum。

 

3、document檢索

document的檢索過程和增刪改略有不一樣:文檔可以從主分片(primary shard)或任意一個複製分片(replicashard)被檢索。

 

檢索過程大體能夠分爲4個階段

階段1:

  客戶端向node1發送檢索請求。node1將做爲協調節點(coordinate node)進行相關工做。

階段2:

  node1根據文檔 _id 計算出命中的primary shard爲P1,node1會找到P1的全部副本,而後經過round-robin隨機輪詢算法,在primary shard以及其全部replica中隨機選擇一個,讓讀請求負載均衡。假如此時隨機選取的是P1,node1會將該請求轉發到P1對應的節點上。

階段3:

  P1處理完該請求將結果返回給協調節點node1。

階段4:

  協調節點node1收到該node2的相應結果,進而將該結果返回給客戶端。

可能的狀況是,一個被索引的文檔已經存在於主分片上卻還沒來得及同步到複製分片上。這時複製分片會報告文檔未找到,主分片會成功返回文檔。一旦索引請求成功返回給用戶,文檔則在主分片和複製分片都是可用的。
對與mget和bulk批量請求,與單文檔檢索還有一點區別,差異是協調節點須要計算每一個文檔所在的分片。它把多文檔請求拆成每一個分片的對文檔請求,而後轉發每一個參與的節點。一旦接收到每一個節點的應答,而後整理這些響應組合爲一個單獨的響應,最後返回給客戶端。
 
 
 
 

 

  參考文獻:

  《elasticsearch-權威指南》

 

  若有錯誤的地方還請留言指正。

  原創不易,轉載請註明原文地址:http://www.javashuo.com/article/p-qdjxjksb-cn.html

相關文章
相關標籤/搜索