1. 程式人生 > >Elasticsearch 分散式文件儲存

Elasticsearch 分散式文件儲存

路由文件到分片

 當你索引一個文件,它被儲存在單獨一個主分片上。Elasticsearch是如何知道文件屬於哪個分片的呢?當你建立一個新文件,它是如何知道是應該儲存在分片1還是分片2上的呢?
程序不能是隨機的,因為我們將來要檢索文件。事實上,它根據一個簡單的演算法決定:
shard = hash(routing) % number_of_primary_shards
routing值是一個任意字串,它預設是_id但也可以自定義。這個routing字串通過雜湊函式生成一個數字,然後除以主切片的數量得到一個餘數(remainder),餘數的範圍永遠是0到number_of_primary_shards - 1,這個數字就是特定文件所在的分片。這也解釋了為什麼主分片的數量只能在建立索引時定義且不能修改:如果主分片的數量在未來改變了,所有先前的路由值就失效了,文件也就永遠找不到了。
 所有的文件API(get、index、delete、bulk、update、mget)都接收一個routing引數,它用來自定義文件到分片的對映。自定義路由值可以確保所有相關文件——例如屬於同一個人的文件——被儲存在同一分片上。

主分片和複製分片如何互動

為了闡述意圖,我們假設有三個節點的叢集。它包含一個叫做bblogs的索引並擁有兩個主分片。每個主分片有兩個複製分片。相同的分片不會放在同一個節點上,所以我們的叢集是這樣的:

這裡寫圖片描述

我們能夠傳送請求給叢集中任意一個節點。每個節點都有能力處理任意請求。每個節點都知道任意文件所在的節點,所以也可以將請求轉發到需要的節點。下面的例子中,我們將傳送所有請求給Node 1,這個節點我們將會稱之為請求節點(requesting node)

新建、索引和刪除文件

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

這裡寫圖片描述

下面我們羅列在主分片和複製分片上成功新建、索引或刪除一個文件必要的順序步驟:

客戶端給Node 1傳送新建、索引或刪除請求。
節點使用文件的_id確定文件屬於分片0。它轉發請求到Node 3,分片0位於這個節點上。
Node 3在主分片上執行請求,如果成功,它轉發請求到相應的位於Node 1和Node 2的複製節點上。當所有的複製節點報告成功,Node 3報告成功到請求的節點,請求的節點再報告給客戶端。

客戶端接收到成功響應的時候,文件的修改已經被應用於主分片和所有的複製分片。你的修改生效了。

有很多可選的請求引數允許你更改這一過程。你可能想犧牲一些安全來提高效能。這一選項很少使用因為Elasticsearch已經足夠快,不過為了內容的完整我們將做一些闡述。

replication

  複製預設的值是sync。這將導致主分片得到複製分片的成功響應後才返回。

  如果你設定replication為async,請求在主分片上被執行後就會返回給客戶端。它依舊會轉發請求給複製節點,但你將不知道複製節點成功與否。

  上面的這個選項不建議使用。預設的sync複製允許Elasticsearch強制反饋傳輸。async複製可能會因為在不等待其它分片就緒的情況下發送過多的請求而使Elasticsearch過載。

consistency

   預設主分片在嘗試寫入時需要規定數量(quorum)或過半的分片(可以是主節點或複製節點)可用。這是防止資料被寫入到錯的網路分割槽。規定的數量計算公式如下:
int( (primary + number_of_replicas) / 2 ) + 1
consistency允許的值為one(只有一個主分片),all(所有主分片和複製分片)或者預設的quorum或過半分片。

注意number_of_replicas是在索引中的的設定,用來定義複製分片的數量,而不是現在活動的複製節點的數量。如果你定義了索引有3個複製節點,那規定數量是:
  int( (primary + 3 replicas) / 2 ) + 1 = 3
但如果你只有2個節點,那你的活動分片不夠規定數量,也就不能索引或刪除任何文件。

timeout

當分片副本不足時會怎樣?Elasticsearch會等待更多的分片出現。預設等待一分鐘。如果需要,你可以設定timeout引數讓它終止的更早:100表示100毫秒,30s表示30秒。

檢索文件

文件能夠從主分片或任意一個複製分片被檢索。

這裡寫圖片描述

下面我們羅列在主分片或複製分片上檢索一個文件必要的順序步驟:

客戶端給Node 1傳送get請求。
節點使用文件的_id確定文件屬於分片0。分片0對應的複製分片在三個節點上都有。此時,它轉發請求到Node 2。
Node 2返回文件(document)給Node 1然後返回給客戶端。

對於讀請求,為了平衡負載,請求節點會為每個請求選擇不同的分片——它會迴圈所有分片副本。

可能的情況是,一個被索引的文件已經存在於主分片上卻還沒來得及同步到複製分片上。這時複製分片會報告文件未找到,主分片會成功返回文件。一旦索引請求成功返回給使用者,文件則在主分片和複製分片都是可用的。

區域性更新文件

update API 結合了之前提到的讀和寫的模式。

這裡寫圖片描述

  下面我們羅列執行區域性更新必要的順序步驟:

客戶端給Node 1傳送更新請求。
它轉發請求到主分片所在節點Node 3。
Node 3從主分片檢索出文檔,修改_source欄位的JSON,然後在主分片上重建索引。如果有其他程序修改了文件,它以retry_on_conflict設定的次數重複步驟3,都未成功則放棄。
如果Node 3成功更新文件,它同時轉發文件的新版本到Node 1和Node 2上的複製節點以重建索引。當所有複製節點報告成功,Node 3返回成功給請求節點,然後返回給客戶端。

update API還接受《新建、索引和刪除》章節提到的routing、replication、consistency和timout引數。

多文件模式

mget和bulk API與單獨的文件類似。差別是請求節點知道每個文件所在的分片。它把多文件請求拆成每個分片的對文件請求,然後轉發每個參與的節點。

一旦接收到每個節點的應答,然後整理這些響應組合為一個單獨的響應,最後返回給客戶端。

這裡寫圖片描述

下面我們將羅列通過一個mget請求檢索多個文件的順序步驟:

客戶端向Node 1傳送mget請求。
Node 1為每個分片構建一個多條資料檢索請求,然後轉發到這些請求所需的主分片或複製分片上。當所有回覆被接收,Node 1構建響應並返回給客戶端。

routing 引數可以被docs中的每個文件設定。

這裡寫圖片描述

下面我們將羅列使用一個bulk執行多個create、index、delete和update請求的順序步驟:

客戶端向Node 1傳送bulk請求。
Node 1為每個分片構建批量請求,然後轉發到這些請求所需的主分片上。
主分片一個接一個的按序執行操作。當一個操作執行完,主分片轉發新文件(或者刪除部分)給對應的複製節點,然後執行下一個操作。一旦所有複製節點報告所有操作已成功完成,節點就報告success給請求節點,後者(請求節點)整理響應並返回給客戶端。

bulk API還可以在最上層使用replication和consistency引數,routing引數則在每個請求的元資料中使用。