https://www.elastic.co/guide/cn/elasticsearch/guide/cn/routing-value.html#routing-value
路由一個文檔到一個分片中
當索引一個文檔的時候,文檔會被存儲到一個主分片中。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 之間的余數,就是我們所尋求的文檔所在分片的位置。
這就解釋了為什么我們要在創(chuàng)建索引的時候就確定好主分片的數量并且永遠不會改變這個數量:因為如果數量變化了,那么所有之前路由的值都會無效,文檔也再也找不到了。
新建、索引和刪除文檔
新建、索引和刪除必須在主分片上面完成之后才能被復制到相關的副本分片。

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

以下是從主分片或者副本分片檢索文檔的步驟順序:
- 客戶端向
Node 1發(fā)送獲取請求。 - 節(jié)點使用文檔的
_id來確定文檔屬于分片 0 。分片 0 的副本分片存在于所有的三個節(jié)點上。 在這種情況下,它將請求轉發(fā)到Node 2。 -
Node 2將文檔返回給Node 1,然后將文檔返回給客戶端。
在處理讀取請求時,協(xié)調結點在每次請求的時候都會通過輪詢所有的副本分片來達到負載均衡。
在文檔被檢索時,已經被索引的文檔可能已經存在于主分片上但是還沒有復制到副本分片。 在這種情況下,副本分片可能會報告文檔不存在,但是主分片可能成功返回文檔。 一旦索引請求成功返回給用戶,文檔在主分片和副本分片都是可用的。
局部更新文檔

以下是部分更新一個文檔的步驟:
- 客戶端向
Node 1發(fā)送更新請求。 - 它將請求轉發(fā)到主分片所在的
Node 3。 -
Node 3從主分片檢索文檔,修改_source字段中的 JSON ,并且嘗試重新索引主分片的文檔。 如果文檔已經被另一個進程修改,它會重試步驟 3 ,超過retry_on_conflict次后放棄。 - 如果
Node 3成功地更新文檔,它將新版本的文檔并行轉發(fā)到Node 1和Node 2上的副本分片,重新建立索引。 一旦所有副本分片都返回成功,Node 3向協(xié)調節(jié)點也返回成功,協(xié)調節(jié)點向客戶端返回成功。
多文檔模式
mget 和 bulk API 的模式類似于單文檔模式。區(qū)別在于協(xié)調節(jié)點知道每個文檔存在于哪個分片中。 它將整個多文檔請求分解成 每個分片 的多文檔請求,并且將這些請求并行轉發(fā)到每個參與節(jié)點。
協(xié)調節(jié)點一旦收到來自每個節(jié)點的應答,就將每個節(jié)點的響應收集整理成單個響應,返回給客戶端。

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

bulk API按如下步驟順序執(zhí)行:
- 客戶端向
Node 1發(fā)送bulk請求。 -
Node 1為每個節(jié)點創(chuàng)建一個批量請求,并將這些請求并行轉發(fā)到每個包含主分片的節(jié)點主機。 - 主分片一個接一個按順序執(zhí)行每個操作。當每個操作成功時,主分片并行轉發(fā)新文檔(或刪除)到副本分片,然后執(zhí)行下一個操作。 一旦所有的副本分片報告所有操作成功,該節(jié)點將向協(xié)調節(jié)點報告成功,協(xié)調節(jié)點將這些響應收集整理并返回給客戶端。
分頁
- 在分布式系統(tǒng)中深度分頁
理解為什么深度分頁是有問題的,我們可以假設在一個有 5 個主分片的索引中搜索。 當我們請求結果的第一頁(結果從 1 到 10 ),每一個分片產生前 10 的結果,并且返回給 協(xié)調節(jié)點 ,協(xié)調節(jié)點對 50 個結果排序得到全部結果的前 10 個。
現(xiàn)在假設我們請求第 1000 頁--結果從 10001 到 10010 。所有都以相同的方式工作除了每個分片不得不產生前10010個結果以外。 然后協(xié)調節(jié)點對全部 50050 個結果排序最后丟棄掉這些結果中的 50040 個結果。
可以看到,在分布式系統(tǒng)中,對結果排序的成本隨分頁的深度成指數上升。這就是 web 搜索引擎對任何查詢都不要返回超過 1000 個結果的原因。