Elasticsearch之分布式文檔存儲

路由一個文檔到一個分片中

當索引一個文檔的時候,文檔會被存儲到一個主分片中。 Elasticsearch 如何知道一個文檔應該存放到哪個分片中呢?當我們創(chuàng)建文檔時,它如何決定這個文檔應當被存儲在分片 1 還是分片 2 中呢?

實際上,這個過程是根據下面這個公式決定的:

shard = hash(routing) % number_of_primary_shards

routing 是一個可變值,默認是文檔的 _id ,也可以設置成一個自定義的值。 routing 通過 hash 函數生成一個數字,然后這個數字再除以 number_of_primary_shards (主分片的數量)后得到 余數 。這個分布在 0 到 number_of_primary_shards-1 之間的余數,就是我們所尋求的文檔所在分片的位置。

所有的文檔 API( get 、 index 、 delete 、 bulk 、 update 以及 mget )都接受一個叫做 routing 的路由參數 ,通過這個參數我們可以自定義文檔到分片的映射。

主分片與副本分片如何交互

  1. 我們可以發(fā)送請求到集群中的任一節(jié)點。 每個節(jié)點都有能力處理任意請求。 每個節(jié)點都知道集群中任一文檔位置,所以可以直接將請求轉發(fā)到需要的節(jié)點上。
  2. 當發(fā)送請求的時候, 為了擴展負載,更好的做法是輪詢集群中所有的節(jié)點。

新建、刪除、索引文檔


以下是在主副分片和任何副本分片上面 成功新建,索引和刪除文檔所需要的步驟順序:

  1. 客戶端向 Node 1 發(fā)送新建、索引或者刪除請求。
  2. 節(jié)點使用文檔的 _id 確定文檔屬于分片 0 。請求會被轉發(fā)到 Node 3,因為分片 0 的主分片目前被分配在Node 3 上。
  3. Node 3 在主分片上面執(zhí)行請求。如果成功了,它將請求并行轉發(fā)到 Node 1 和 Node 2 的副本分片上。一旦所有的副本分片都報告成功, Node 3 將向協調節(jié)點報告成功,協調節(jié)點向客戶端報告成功。
  4. 在客戶端收到成功響應時,文檔變更已經在主分片和所有副本分片執(zhí)行完成,變更是安全的。

有一些可選的請求參數允許您影響這個過程,可能以數據安全為代價提升性能。這些選項很少使用,因為Elasticsearch已經很快,但是為了完整起見,在這里闡述如下:

  1. consistency,即一致性。在默認設置下,即使僅僅是在試圖執(zhí)行一個操作之前,主分片都會要求 必須要有 規(guī)定數量(quorum)(或者換種說法,也即必須要有大多數)的分片副本處于活躍可用狀態(tài),才會去執(zhí)行操作(其中分片副本可以是主分片或者副本分片)。這是為了避免在發(fā)生網絡分區(qū)故障(network partition)的時候進行操作,進而導致數據不一致。規(guī)定數量即:
int( (primary + number_of_replicas) / 2 ) + 1
  1. timeout。如果沒有足夠的副本分片會發(fā)生什么? Elasticsearch會等待,希望更多的分片出現。默認情況下,它最多等待1分鐘。 如果你需要,你可以使用 timeout 參數 使它更早終止: 100 100毫秒,30s 是30秒。

取回單個文檔


以下是從主分片或者副本分片檢索文檔的步驟順序:

  1. 客戶端向 Node 1 發(fā)送獲取請求。
  2. 節(jié)點使用文檔的 _id 來確定文檔屬于分片 0 。分片 0 的副本分片存在于所有的三個節(jié)點上。 在這種情況下,它將請求轉發(fā)到 Node 2 。
  3. Node 2 將文檔返回給 Node 1 ,然后將文檔返回給客戶端。

備注:

  1. 在處理讀取請求時,協調結點在每次請求的時候都會通過輪詢所有的副本分片來達到負載均衡。
  2. 在文檔被檢索時,已經被索引的文檔可能已經存在于主分片上但是還沒有復制到副本分片。 在這種情況下,副本分片可能會報告文檔不存在,但是主分片可能成功返回文檔。 一旦索引請求成功返回給用戶,文檔在主分片和副本分片都是可用的。

局部更新文檔


以下是部分更新一個文檔的步驟:

  1. 客戶端向 Node 1 發(fā)送更新請求。
  2. 它將請求轉發(fā)到主分片所在的 Node 3 。
  3. Node 3 從主分片檢索文檔,修改 _source 字段中的 JSON ,并且嘗試重新索引主分片的文檔。 如果文檔已經被另一個進程修改,它會重試步驟 3 ,超過 retry_on_conflict 次后放棄。
  4. 如果 Node 3 成功地更新文檔,它將新版本的文檔并行轉發(fā)到 Node 1 和 Node 2 上的副本分片,重新建立索引。 一旦所有副本分片都返回成功, Node 3 向協調節(jié)點也返回成功,協調節(jié)點向客戶端返回成功。

備注:當主分片把更改轉發(fā)到副本分片時, 它不會轉發(fā)更新請求。 相反,它轉發(fā)完整文檔的新版本

多文檔模式

mget 和 bulk API 的 模式類似于單文檔模式。區(qū)別在于協調節(jié)點知道每個文檔存在于哪個分片中。 它將整個多文檔請求分解成 每個分片 的多文檔請求,并且將這些請求并行轉發(fā)到每個參與節(jié)點。

  • 使用 mget 取回多個文檔



    以下是使用單個 mget 請求取回多個文檔所需的步驟順序:

    1. 客戶端向 Node 1 發(fā)送 mget 請求。
    2. Node 1 為每個分片構建多文檔獲取請求,然后并行轉發(fā)這些請求到托管在每個所需的主分片或者副本分片的節(jié)點上。一旦收到所有答復, Node 1 構建響應并將其返回給客戶端。
  • 使用 bulk 修改多個文檔



    bulk API 按如下步驟順序執(zhí)行:

    1. 客戶端向 Node 1 發(fā)送 bulk 請求。
    2. Node 1 為每個節(jié)點創(chuàng)建一個批量請求,并將這些請求并行轉發(fā)到每個包含主分片的節(jié)點主機。
    3. 主分片一個接一個按順序執(zhí)行每個操作。當每個操作成功時,主分片并行轉發(fā)新文檔(或刪除)到副本分片,然后執(zhí)行下一個操作。一旦所有的副本分片報告所有操作成功,該節(jié)點將向協調節(jié)點報告成功,協調節(jié)點將這些響應收集整理并返回給客戶端。

參考資料

Elasticsearch: 權威指南

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容