ElasticSearch 的主旨是隨時可用和按需擴容。 而擴容可以通過購買性能更強大(垂直擴容,或 縱向擴容) 或者數量更多的服務器(水平擴容,或 橫向擴容 )來實現。
雖然 ElasticSearch 可以獲益於更強大的硬件設備,但是垂直擴容是有極限的。 真正的擴容能力是來自於水平擴容–為集群添加更多的節點,並且將負載壓力和穩定性分散到這些節點中。
對於大多數的數據庫而言,通常需要對應用程序進行非常大的改動,才能利用上橫向擴容的新增資源。 與之相反的是,ElastiSearch天生就是分布式的 ,它知道如何通過管理多節點來提高擴容性和可用性。 這也意味着你的應用無需關注這個問題。
一個運行中的 ElasticSearch 實例稱為一個節點,而集群是由一個或者多個擁有相同 cluster.name 配置的節點組成, 它們共同承擔數據和負載的壓力。當有節點加入集群中或者從集群中移除節點時,集群將會重新平均分布所有的數據。
當一個節點被選舉成為主節點時, 它將負責管理:集群范圍內的所有變更,例如增加、刪除索引,或者增加、刪除節點等。而主節點並不需要涉及到文檔級別的變更和搜索等操作,所以當集群只擁有一個主節點的情況下,即使流量的增加它也不會成為瓶頸。 任何節點都可以成為主節點。我們的示例集群就只有一個節點,所以它同時也成為了主節點。
作為用戶,我們可以將請求發送到集群中的任何節點 ,包括主節點。 每個節點都知道任意文檔所處的位置,並且能夠將我們的請求直接轉發到存儲我們所需文檔的節點。 無論我們將請求發送到哪個節點,它都能負責從各個包含我們所需文檔的節點收集回數據,並將最終結果返回給客戶端。 ElasticSearch 對這一切的管理都是透明的。
集群健康:
ElasticSearch 的集群監控信息中包含了許多的統計數據,其中最為重要的一項就是 集群健康 , 它在 status 字段中展示為 green 、 yellow 或者 red 。
在一個不包含任何索引的空集群中,它將會有一個類似於如下所示的返回內容:
{
"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
}
green:
所有的主分片和副本分片都正常運行。
yellow:
所有的主分片都正常運行,但不是所有的副本分片都正常運行。
red:
有主分片沒能正常運行。
添加索引
我們往 ElasticSearch 添加數據時需要用到索引。 索引實際上是指向一個或者多個物理分片的邏輯命名空間 。
一個分片是一個底層的工作單元,它僅保存了全部數據中的一部分。 在分片內部機制中,我們將詳細介紹分片是如何工作的,而現在我們只需知道一個分片是一個 Lucene 的實例,以及它本身就是一個完整的搜索引擎。 我們的文檔被存儲和索引到分片內,但是應用程序是直接與索引而不是與分片進行交互。
ElasticSearch是利用分片將數據分發到集群內各處的。分片是數據的容器,文檔保存在分片內,分片又被分配到集群內的各個節點里。 當你的集群規模擴大或者縮小時, ElasticSearch會自動的在各節點中遷移分片,使得數據仍然均勻分布在集群里。
一個分片可以是主分片或者副本分片。 索引內任意一個文檔都歸屬於一個主分片,所以主分片的數目決定着索引能夠保存的最大數據量。
一個副本分片只是一個主分片的拷貝。 副本分片作為硬件故障時保護數據不丟失的冗余備份,並為搜索和返回文檔等讀操作提供服務。
在索引建立的時候就已經確定了主分片數,但是副本分片數可以隨時修改。
讓我們在包含一個空節點的集群內創建名為 blogs 的索引。 索引在默認情況下會被分配5個主分片, 但是為了演示目的,我們將分配3個主分片和一份副本(每個主分片擁有一個副本分片):
PUT /blogs
{
"settings" : {
"number_of_shards" : 3,
"number_of_replicas" : 1
}
}
如果我們現在查看集群健康, 我們將看到如下內容:
{
"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
}
集群的健康狀況為 yellow 則表示全部主分片都正常運行(集群可以正常服務所有請求),但是副本分片沒有全部處在正常狀態。 實際上,所有3個副本分片都是 unassigned狀態,它們都沒有被分配到任何節點。 在同一個節點上既保存原始數據又保存副本是沒有意義的,因為一旦失去了那個節點,我們也將丟失該節點上的所有副本數據。
添加故障轉移
當集群中只有一個節點在運行時,意味着會有一個單點故障問題——沒有冗余。 幸運的是,我們只需再啟動一個節點即可防止數據丟失。
為了測試第二個節點啟動后的情況,你可以在同一個目錄內,完全依照啟動第一個節點的方式來啟動一個新節點。多個節點可以共享同一個目錄。
當你在同一台機器上啟動了第二個節點時,只要它和第一個節點有同樣的 cluster.name 配置,它就會自動發現集群並加入到其中。 但是在不同機器上啟動節點的時候,為了加入到同一集群,你需要配置一個可連接到的單播主機列表。 詳細信息請查看最好使用單播代替組播。
當第二個節點加入到集群后,3個副本分片將會分配到這個節點上——每個主分片對應一個副本分片。 這意味着當集群內任何一個節點出現問題時,我們的數據都完好無損。
所有新近被索引的文檔都將會保存在主分片上,然后被並行的復制到對應的副本分片上。這就保證了我們既可以從主分片又可以從副本分片上獲得文檔。
cluster-health 現在展示的狀態為 green ,這表示所有6個分片(包括3個主分片和3個副本分片)都在正常運行。
水平擴容
怎樣為我們的正在增長中的應用程序按需擴容呢?當啟動了第三個節點,我們的集群將會看起來如圖,擁有三個節點的集群,ES為了分散負載而對分片進行重新分配所示。

Node 1 和 Node 2 上各有一個分片被遷移到了新的 Node 3 節點,現在每個節點上都擁有2個分片。 這表示每個節點的硬件資源(CPU, RAM, I/O)將被更少的分片所共享,每個分片的性能將會得到提升。
分片是一個功能完整的搜索引擎,它擁有使用一個節點上的所有資源的能力。 我們這個擁有6個分片(3個主分片和3個副本分片)的索引可以最大擴容到6個節點,每個節點上存在一個分片,並且每個分片擁有所在節點的全部資源。
主分片的數目在索引創建時 就已經確定了下來。實際上,這個數目定義了這個索引能夠存儲的最大數據量(實際大小取決於你的數據、硬件和使用場景)。但是,讀操作,搜索和返回數據可以同時被主分片或副本分片所處理,所以當你擁有越多的副本分片時,也將擁有越高的吞吐量。
應對故障

我們關閉的節點是一個主節點。而集群必須擁有一個主節點來保證正常工作,所以發生的第一件事情就是選舉一個新的主節點 Node 2。
在我們關閉 Node 1 的同時也失去了主分片 1 和 2 ,並且在缺失主分片的時候索引也不能正常工作。 如果此時來檢查集群的狀況,我們看到的狀態將會為 red :不是所有主分片都在正常工作。
幸運的是,在其它節點上存在着這兩個主分片的完整副本, 所以新的主節點立即將這些分片在 Node 2 和 Node 3 上對應的副本分片提升為主分片。
這個提升主分片的過程是瞬間發生的,如同按下一個開關一般,集群恢復green狀態。
如果我們同樣關閉了 Node 2 ,我們的程序依然可以保持在不丟任何數據的情況下運行,因為 Node 3 為每一個分片都保留着一份副本。
