Elasticsearch從入門到精通之Elasticsearch集羣內的原理

上一章節我介紹了Elasticsearch安裝與運行,本章節及後續章節將全方位介紹 Elasticsearch 的工做原理

在這個章節中,我將會再進一步介紹 cluster 、 node 、 shard 等經常使用術語,Elastisearch 的擴容機制, 以及如何處理硬件故障的內容。html

一、分佈式特性

Elasticsearch 能夠橫向擴展至數百(甚至數千)的服務器節點,同時能夠處理PB級數據。Elasticsearch 天生就是分佈式的,而且在設計時屏蔽了分佈式的複雜性。node

Elasticsearch 在分佈式方面幾乎是透明的。教程中並不要求瞭解分佈式系統、分片、集羣發現或其餘的各類分佈式概念。可使用筆記本上的單節點輕鬆地運行教程裏的程序,但若是你想要在 100 個節點的集羣上運行程序,一切依然順暢。git

Elasticsearch 儘量地屏蔽了分佈式系統的複雜性。這裏列舉了一些在後臺自動執行的操做:github

  • 分配文檔到不一樣的容器 或 分片 中,文檔能夠儲存在一個或多個節點中
  • 按集羣節點來均衡分配這些分片,從而對索引和搜索過程進行負載均衡
  • 複製每一個分片以支持數據冗餘,從而防止硬件故障致使的數據丟失
  • 將集羣中任一節點的請求路由到存有相關數據的節點
  • 集羣擴容時無縫整合新節點,從新分配分片以便從離羣節點恢復

二、集羣原理

ElasticSearch 的主旨是隨時可用和按需擴容。 而擴容能夠經過購買性能更強大( 垂直擴容 ,或 縱向擴容)  或者數量更多的服務器( 水平擴容 ,或 橫向擴容 )來實現。數據庫

雖然 Elasticsearch 能夠獲益於更強大的硬件設備,可是垂直擴容是有極限的。 真正的擴容能力是來自於水平擴容--爲集羣添加更多的節點,而且將負載壓力和穩定性分散到這些節點中。json

對於大多數的數據庫而言,一般須要對應用程序進行很是大的改動,才能利用上橫向擴容的新增資源。 與之相反的是,ElastiSearch天生就是 分佈式的 ,它知道如何經過管理多節點來提升擴容性和可用性。 這也意味着你的應用無需關注這個問題。服務器

2.一、空集羣

若是咱們啓動了一個單獨的節點,裏面不包含任何的數據和 索引,那咱們的集羣看起來就像下圖1同樣。app

圖 1. 包含空內容節點的集羣負載均衡

包含空內容節點的集羣

 

一個運行中的 Elasticsearch 實例稱爲一個 節點,而集羣是由一個或者多個擁有相同 cluster.name 配置的節點組成, 它們共同承擔數據和負載的壓力。當有節點加入集羣中或者從集羣中移除節點時,集羣將會從新平均分佈全部的數據。curl

當一個節點被選舉成爲  節點時, 它將負責管理集羣範圍內的全部變動,例如增長、刪除索引,或者增長、刪除節點等。 而主節點並不須要涉及到文檔級別的變動和搜索等操做,因此當集羣只擁有一個主節點的狀況下,即便流量的增長它也不會成爲瓶頸。 任何節點均可以成爲主節點。咱們的示例集羣就只有一個節點,因此它同時也成爲了主節點。

做爲用戶,咱們能夠將請求發送到 集羣中的任何節點 ,包括主節點。 每一個節點都知道任意文檔所處的位置,而且可以將咱們的請求直接轉發到存儲咱們所需文檔的節點。 不管咱們將請求發送到哪一個節點,它都能負責從各個包含咱們所需文檔的節點收集回數據,並將最終結果返回給客戶端。 Elasticsearch 對這一切的管理都是透明的。

2.二、集羣健康

lasticsearch 的集羣監控信息中包含了許多的統計數據,其中最爲重要的一項就是 集羣健康 , 它在 status 字段中展現爲 green 、 yellow 或者 red 。

GET /_cluster/health
 

在一個不包含任何索引的空集羣中,它將會有一個相似於以下所示的返回內容:

{
   "cluster_name":          "elasticsearch",
   "status":                "green", 
   "timed_out":             false,
   "number_of_nodes":       1,
   "number_of_data_nodes":  1,
   "active_primary_shards": 0,
   "active_shards":         0,
   "relocating_shards":     0,
   "initializing_shards":   0,
   "unassigned_shards":     0
}
 

status 字段指示着當前集羣在整體上是否工做正常。它的三種顏色含義以下:

green
全部的主分片和副本分片都正常運行。
yellow
全部的主分片都正常運行,但不是全部的副本分片都正常運行。
red
有主分片沒能正常運行。

 

2.三、新增索引

咱們往 Elasticsearch 添加數據時須要用到索引 —— 保存相關數據的地方。 索引其實是指向一個或者多個物理分片 的邏輯命名空間 。

一個分片 是一個底層的工做單元 ,它僅保存了 所有數據中的一部分。 在分片內部機制中,咱們將詳細介紹分片是如何工做的,而如今咱們只需知道一個分片是一個 Lucene 的實例,以及它自己就是一個完整的搜索引擎文件。 咱們的文檔被存儲和索引到分片內,可是應用程序是直接與索引而不是與分片進行交互。

Elasticsearch 是利用分片將數據分發到集羣內各處的。分片是數據的容器,文檔保存在分片內,分片又被分配到集羣內的各個節點裏。 當你的集羣規模擴大或者縮小時, Elasticsearch 會自動的在各節點中遷移分片,使得數據仍然均勻分佈在集羣裏。

一個分片能夠是  分片或者 副本 分片。 索引內任意一個文檔都歸屬於一個主分片,因此主分片的數目決定着索引可以保存的最大數據量。

注意

技術上來講,一個主分片最大可以存儲 Integer.MAX_VALUE - 128 個文檔,可是實際最大值還須要參考你的使用場景:包括你使用的硬件, 文檔的大小和複雜程度,索引和查詢文檔的方式以及你指望的響應時長。

一個副本分片只是一個主分片的拷貝。 副本分片做爲硬件故障時保護數據不丟失的冗餘備份,併爲搜索和返回文檔等讀操做提供服務。

在索引創建的時候就已經肯定了主分片數,可是副本分片數能夠隨時修改。

讓咱們在包含一個空節點的集羣內建立名爲 shops 的索引。 索引在默認狀況下會被分配5個主分片, 可是爲了演示目的,咱們將分配3個主分片和一份副本(每一個主分片擁有一個副本分片):

PUT /shops 
{
   "settings" : {
      "number_of_shards" : 3,
      "number_of_replicas" : 1
   }
}
 

咱們的集羣如今是圖 2 「擁有一個索引的單節點集羣」。全部3個主分片都被分配在 Node 1 。

圖 2. 擁有一個索引的單節點集羣

擁有一個索引的單節點集羣

 

若是咱們如今查看集羣健康 咱們將看到以下內容:

{
  "cluster_name": "elasticsearch",
  "status": "yellow", 
  "timed_out": false,
  "number_of_nodes": 1,
  "number_of_data_nodes": 1,
  "active_primary_shards": 3,
  "active_shards": 3,
  "relocating_shards": 0,
  "initializing_shards": 0,
  "unassigned_shards": 3, 
  "delayed_unassigned_shards": 0,
  "number_of_pending_tasks": 0,
  "number_of_in_flight_fetch": 0,
  "task_max_waiting_in_queue_millis": 0,
  "active_shards_percent_as_number": 50
}

集羣 status 值爲 yellow 。

沒有被分配到任何節點的副本數。

集羣的健康情況爲 yellow 則表示所有 分片都正常運行(集羣能夠正常服務全部請求),可是副本 分片沒有所有處在正常狀態。 實際上,全部3個副本分片都是 unassigned —— 它們都沒有被分配到任何節點。 在同一個節點上既保存原始數據又保存副本是沒有意義的,由於一旦失去了那個節點,咱們也將丟失該節點上的全部副本數據。

當前咱們的集羣是正常運行的,可是在硬件故障時有丟失數據的風險。

2.四、故障轉移

當集羣中只有一個節點在運行時,意味着會有一個單點故障問題——沒有冗餘。 幸運的是,咱們只需再啓動一個節點便可防止數據丟失。

若是啓動了第二個節點,咱們的集羣將會如圖 3 「擁有兩個節點的集羣——全部主分片和副本分片都已被分配」所示。

圖 3. 擁有兩個節點的集羣——全部主分片和副本分片都已被分配

擁有兩個節點的集羣

 

當第二個節點加入到集羣后,3個 副本分片 將會分配到這個節點上——每一個主分片對應一個副本分片。 這意味着當集羣內任何一個節點出現問題時,咱們的數據都無缺無損。

全部新近被索引的文檔都將會保存在主分片上,而後被並行的複製到對應的副本分片上。這就保證了咱們既能夠從主分片又能夠從副本分片上得到文檔。

cluster-health 如今展現的狀態爲 green ,這表示全部6個分片(包括3個主分片和3個副本分片)都在正常運行。

{
  "cluster_name": "elasticsearch",
  "status": "green", 
  "timed_out": false,
  "number_of_nodes": 2,
  "number_of_data_nodes": 2,
  "active_primary_shards": 3,
  "active_shards": 6,
  "relocating_shards": 0,
  "initializing_shards": 0,
  "unassigned_shards": 0,
  "delayed_unassigned_shards": 0,
  "number_of_pending_tasks": 0,
  "number_of_in_flight_fetch": 0,
  "task_max_waiting_in_queue_millis": 0,
  "active_shards_percent_as_number": 100
}

集羣 status 值爲 green 。

咱們的集羣如今不只僅是正常運行的,而且還處於 始終可用 的狀態。

2.五、水平擴容

怎樣爲咱們的正在增加中的應用程序按需擴容呢? 當啓動了第三個節點,咱們的集羣將會看起來如圖 4 「擁有三個節點的集羣——爲了分散負載而對分片進行從新分配」所示。

圖 4. 擁有三個節點的集羣——爲了分散負載而對分片進行從新分配

擁有三個節點的集羣

 

Node 1 和 Node 2 上各有一個分片被遷移到了新的 Node 3 節點,如今每一個節點上都擁有2個分片,而不是以前的3個。 這表示每一個節點的硬件資源(CPU, RAM, I/O)將被更少的分片所共享,每一個分片的性能將會獲得提高。

分片是一個功能完整的搜索引擎,它擁有使用一個節點上的全部資源的能力。 咱們這個擁有6個分片(3個主分片和3個副本分片)的索引能夠最大擴容到6個節點,每一個節點上存在一個分片,而且每一個分片擁有所在節點的所有資源。

2.5.一、更多的擴容

可是若是咱們想要擴容超過6個節點怎麼辦呢?

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

在運行中的集羣上是能夠動態調整副本分片數目的 ,咱們能夠按需伸縮集羣。讓咱們把副本數從默認的 1增長到 2 :

PUT /shops/_settings
{
   "number_of_replicas" : 2
}
 

如圖 5 「將參數 number_of_replicas 調大到 2」所示, shops 索引如今擁有9個分片:3個主分片和6個副本分片。 這意味着咱們能夠將集羣擴容到9個節點,每一個節點上一個分片。相比原來3個節點時,集羣搜索性能能夠提高 3 倍。

圖 5. 將參數 number_of_replicas 調大到 2

擁有2份副本分片3個節點的集羣

注意

固然,若是隻是在相同節點數目的集羣上增長更多的副本分片並不能提升性能,由於每一個分片從節點上得到的資源會變少。 你須要增長更多的硬件資源來提高吞吐量。

可是更多的副本分片數提升了數據冗餘量:按照上面的節點配置,咱們能夠在失去2個節點的狀況下不丟失任何數據。

2.六、應對故障

咱們以前說過 Elasticsearch 能夠應對節點故障,接下來讓咱們嘗試下這個功能。 若是咱們關閉第一個節點,這時集羣的狀態爲圖 6 「關閉了一個節點後的集羣」

圖 6. 關閉了一個節點後的集羣

關閉了一個節點後的集羣

 

咱們關閉的節點是一個主節點。而集羣必須擁有一個主節點來保證正常工做,因此發生的第一件事情就是選舉一個新的主節點: Node 2 。

在咱們關閉 Node 1 的同時也失去了主分片 1 和 2 ,而且在缺失主分片的時候索引也不能正常工做。 若是此時來檢查集羣的情況,咱們看到的狀態將會爲 red :不是全部主分片都在正常工做。

幸運的是,在其它節點上存在着這兩個主分片的完整副本, 因此新的主節點當即將這些分片在 Node 2 和 Node 3 上對應的副本分片提高爲主分片, 此時集羣的狀態將會爲 yellow 。 這個提高主分片的過程是瞬間發生的,如同按下一個開關通常。

爲何咱們集羣狀態是 yellow 而不是 green 呢? 雖然咱們擁有全部的三個主分片,可是同時設置了每一個主分片須要對應2份副本分片,而此時只存在一份副本分片。 因此集羣不能爲 green 的狀態,不過咱們沒必要過於擔憂:若是咱們一樣關閉了 Node 2 ,咱們的程序 依然 能夠保持在不丟任何數據的狀況下運行,由於 Node 3 爲每個分片都保留着一份副本。

若是咱們從新啓動 Node 1 ,集羣能夠將缺失的副本分片再次進行分配,那麼集羣的狀態也將如圖 5 「將參數 number_of_replicas 調大到 2所示。 若是 Node 1 依然擁有着以前的分片,它將嘗試去重用它們,同時僅從主分片複製發生了修改的數據文件。

到目前爲止,你應該對分片如何使得 Elasticsearch 進行水平擴容以及數據保障等知識有了必定了解

相關文章
相關標籤/搜索