一文搞懂 ElasticSearch 集羣,就它了!

大家好,我是頂級架構師。

一、爲什麼要集羣

單臺 Elasticsearch 服務器提供服務,往往都有最大的負載能力,超過這個閾值,服務器性能就會大大降低甚至不可用,所以生產環境中,一般都是運行在指定服務器集羣中。除了負載能力,單點服務器也存在其他問題:

配置服務器集羣時,集羣中節點數量沒有限制,大於等於 2 個節點就可以看做是集羣了。一般出於高性能及高可用方面來考慮集羣中節點數量都是 3 個以上。

二、集羣的概念

一個集羣就是由一個或多個服務器節點組織在一起,共同持有整個的數據,並一起提供索引和搜索功能。

一個 Elasticsearch 集羣有一個唯一的名字標識,這個名字默認就是”elasticsearch”。這個名字是重要的,因爲一個節點只能通過指定某個集羣的名字,來加入這個集羣。

三、(mac/windows)集羣部署

注:本博客是 mac 系統的部署,但本人親測 windows 依舊可以適用,mac 和 windows 上唯一的區別在於 windows 的啓動文件是 bin/elasticsearch.bat

將 ElasticSearch 的解壓文件複製三份,如下所示:

  1. 修改 node-8001 的 config/elasticsearch.yml 文件, 如下
cluster.name: my-application

node.name: node-8001
node.master: true
node.data: true

network.host: localhost

http.port: 8001
transport.tcp.port: 9301

http.cors.enabled: true
http.cors.allow-origin: "*"
  1. 修改 node-8002 的 config/elasticsearch.yml 文件, 如下
cluster.name: my-application

node.name: node-8002
node.master: true
node.data: true

network.host: localhost

http.port: 8002
transport.tcp.port: 9302
discovery.seed_hosts: ["localhost:9301"]
discovery.zen.fd.ping_timeout: 1m
discovery.zen.fd.ping_retries: 5

http.cors.enabled: true
http.cors.allow-origin: "*"
  1. 修改 node-8003 的 config/elasticsearch.yml 文件, 如下
cluster.name: my-application

node.name: node-8003
node.master: true
node.data: true

network.host: localhost

http.port: 8003
transport.tcp.port: 9303
discovery.seed_hosts: ["localhost:9301","localhost:9302"]
discovery.zen.fd.ping_timeout: 1m
discovery.zen.fd.ping_retries: 5

http.cors.enabled: true
http.cors.allow-origin: "*"

然後按照順序執行 bin/elatsicsearch 文件,在 postman 中通過訪問http://localhost:8001/_cluster/health可以看出集羣部署成功!

四、操作演示

1. 單點集羣

我們只啓動上面的 node-8001 的 ES(node-8002 和 node-8003 都沒啓動),爲了演示目的,我們將分配 3 個主分片和一份副本(每個主分片擁有一個副本分片)

通過 chrome 瀏覽器的 Elastic Head 插件,我們可以看出 3 個副本分片都是 Unassigned —— 它們都沒有被分配到任何節點。在同一個節點上既保存原始數據又保存副本是沒有意義的,因爲一旦失去了那個節點,我們也將丟失該節點上的所有副本數據。

2. 故障轉移

當集羣中只有一個節點在運行時,意味着會有一個單點故障問題——沒有冗餘。幸運的是,我們只需再啓動一個節點即可防止數據丟失。當你在同一臺機器上啓動了第二個節點時,只要它和第一個節點有同樣的 cluster.name 配置,它就會自動發現集羣並加入到其中。另外,搜索公衆號 GitHub 猿後臺回覆 “賺錢”,獲取一份驚喜禮包。

但是在不同機器上啓動節點的時候,爲了加入到同一集羣,你需要配置一個可連接到的單播主機列表。之所以配置爲使用單播發現,以防止節點無意中加入集羣。只有在同一臺機器上運行的節點纔會自動組成集羣。

這裏我們直接啓動 node-8002 和 node-8003:

通過 chrome 瀏覽器的 Elastic Head 插件,我們可以看出一切正常!node-8001 前面有星號,說明是主節點。並且有加粗邊框的分片(例如 node-8003 都)是主分片,沒有加粗的分片(例如 node-8002 都)是副本。

3. 水平擴容

主分片的數目在索引創建時就已經確定了下來。實際上,這個數目定義了這個索引能夠存儲的最大數據量。(實際大小取決於你的數據、硬件和使用場景。) 但是,讀操作——搜索和返回數據——可以同時被主分片 或 副本分片所處理,所以當你擁有越多的副本分片時,也將擁有越高的吞吐量。

下面就是在索引創建後,修改副本的數量(案例中是把副本數量修改爲 2),只需要如下的操作:

我們再看看 elasticsearch head 的監控頁面,發現每個節點上已經有三個分片了

4. 應對故障

比如 node-8001 這個主節點某一刻掛掉了(我們直接把 node-8001 的黑窗口關掉來模擬這種情況)。所以下圖很好理解:8001 關掉了,自然是未連接!

我們來查看 8002 端口的情況,發現有有三個副本無法分配,雖然健康狀態是黃色的,但依舊不會影響使用,依舊可以提供服務!

假設經過搶修,現在 8001 點故障已經解決了,那我們該如何將其重新加入集羣中呢?其實我們只需要下面的操作:

第一步:再次修改 config/elasticsearch.yml 文件, 添加下面的一行

第二步:啓動 node-8001,發現 node-8001 已經納入集羣,而且分片正常,但主節點變成了 node-8002 也不影響使用!

五、路由計算 & 分片控制

1. 路由計算

經過上面的操作,我們會有這樣的疑問——當索引一個文檔的時候,文檔會被存儲到一個主分片中。Elasticsearch 如何知道一個文檔應該存放到哪個分片中呢?當我們創建文檔時,它如何決定這個文檔應當被存儲在分片 1 還是分片 2 中呢?

這就引出了下面的路由算法, 這就解釋了爲什麼我們要在創建索引的時候就確定好主分片的數量 並且永遠不會改變這個數量:因爲如果數量變化了,那麼所有之前路由的值都會無效,文檔也再也找不到了。

routing 是一個可變值,默認是文檔的_id,也可以設置成一個自定義的值。

routing 通過 hash 函數生成一個數字,然後這個數字再除以number_of_primary_shards(主分片的數量)後得到餘數 。關注編程技術圈

這個分佈在 0 到number_of_primary_shards-1 之間的餘數,就是我們所尋求的文檔所在分片的位置。

2. 分片控制

比如上圖,zhangsan 文檔經過路由計算找到了 2 號分片,但 2 號分片在三個節點中都存在(node-8001 和 node-8002 保存的是分片的副本)。我們可以發送請求到集羣中的任一節點。每個節點都有能力處理任意請求。

每個節點都知道集羣中任一文檔位置,所以可以直接將請求轉發到需要的節點上。當發送請求的時候, 爲了擴展負載,更好的做法是輪詢集羣中所有的節點。

六、集羣中的讀寫操作流程

1. 寫操作

新建、索引和刪除 請求都是寫操作,必須在主分片上面完成之後才能被複制到相關的副本分片

在客戶端收到成功響應時,文檔變更已經在主分片和所有副本分片執行完成,變更是安全的。有一些可選的請求參數允許您影響這個過程,可能以數據安全爲代價提升性能。這些選項很少使用,因爲 Elasticsearch 已經很快, 但爲了知識的完整性請看下方:

  1. consistency 參數的值可以設爲 one (只要主分片狀態 ok 就允許執行_寫_操作),all(必須要主分片和所有副本分片的狀態沒問題才允許執行_寫_操作), 或 quorum 。默認值爲 quorum , 即大多數的分片副本狀態沒問題就允許執行_寫_操作。

  2. 如果沒有足夠的副本分片會發生什麼?Elasticsearch 會等待,希望更多的分片出現。默認情況下,它最多等待 1 分鐘。如果你需要,你可以使用 timeout 參數使它更早終止:100 100 毫秒,30s 是 30 秒。

2. 讀操作

我們可以從主分片或者從其它任意副本分片檢索文檔

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/iIJFNKYtwl_it_TdddDkww