⑴ ES是什麼
ES是一個基於RESTful web介面並且構建在Apache Lucene之上的開源分布式搜索引擎。
同時ES還是一個分布式文檔資料庫,其中每個欄位均可被索引,而且每個欄位的數據均可被搜索,能夠橫向擴展至數以百計的伺服器存儲以及處理PB級的數據。
可以在極短的時間內存儲、搜索和分析大量的數據。通常作為具有復雜搜索場景情況下的核心發動機。
⑵ ElasticSearch核心之——分布式特性
ES支持集群模式,是一個分布式系統,其好處主要有兩個∶
es集群由多個ES 實例組成。不同集群通過集群名字來區分,可通過 cluster.name 進行修改,默認為elasticsearch。每個ES實例本質上是一個 JVM 進程,且有自己的名字,通過 node.name 進行修改
ES集群相關的數據稱為 cluster state ,主要記錄如下信息∶節點信息,比如節點名稱、連接地址等;索引信息,比如索引名稱、配置等
可以修改 cluster state 的節點稱為master節點,一個集群只能有一個 cluster state 存儲在每個節點上,master維護最新版本並同步給其他節點
master節點是通過集群中所有節點選舉產生的,可以被選舉的節點稱為 master-eligible 節點 ,相關配置如下: node.master: true
處理請求的節點即為coordinating節點,該節點為所有節點的默認角色,不能取消。路由請求到正確的節點處理,比如創建索引的請求到master節點
存儲數據的節點即為data節點,默認節點都是data類型,相關配置如下∶ node.data: true
談及副本和分片兩個概念之前,我們先說一下這兩個概念存在的意義: 解決系統可用性和增大系統容量
我們想像這樣一個場景,我們的數據只存放在一台ES伺服器上,那麼一旦這台ES出現宕機或者其他不可控因素影響的話,我們除了喪失了服務的可用性外,可能還存在著數據丟失的可能。同時,單機服務的存儲容量也無法應對項目對大數據量的要求。
系統可用性可以分為 服務可用性 和 數據可用性
服務可用性 含義為:當前服務掛掉後,是否有其他伺服器頂替當前節點提供服務支持。
數據可用性 含義為:當前服務掛掉後,存儲在當前伺服器上的數據,是否還可以對外提供訪問和修改的服務。
副本可以理解為是某個數據的復制體,副本和源數據內容一致。副本的存在可以有效地滿足系統可用性的需求,比如說,我們可以在原有節點的基礎上復制一個和源節點一模一樣的節點,這樣一旦原有節點掛掉了,另外一個節點也還是可以替代源節點提供服務,而且復制出來的節點擁有和源節點一樣的數據,這樣也保障了數據可用性。
我們在上一小節講到可以使用副本來解決系統可用性的問題,但是這里存在一個問題,不管存在多少個副本(節點),都無法增大源節點的存儲空間。在這個問題上,ES引入了Shard分片這個概念來解決問題。
看完分片的特點後可能還有人不太清楚到底什麼是分片,其實分片是n/1個源節點數據。比如說原ES集群中只有一個主節點,所有的索引數據都存儲在這個節點上。現在我們將某個索引數據分成3份,分別存放在3個ES節點上,那麼每台ES伺服器上就各自有1個分片shard。該索引的所有節點Shard分片的集合,就是索引的全部數據。
下面我們來演示一下:
為了更好的了解ES的分片機制,大家不妨在上面的案例上進一步思考兩個問題:
答案是不能。原因是我們創建索引時定義的分片數量只有3個,且都已經落在了3個節點上。所以即使再增加多一個節點,也不會有對應的Shard分片可以落在新的節點上,並不能擴大 test_shard_index 的數據容量。
答案是不能。因為新增的副本也是分布在這3個節點上,還是利用了同樣的資源。如果要增加吞吐量,還需要新增節點。
通過上面兩個問題,相信大家已經可以認識到分片的重要性,分片數過小,會導致後續無法通過增加節點實現水平擴容;(副本)分片數過大會導致一個節點上分布過多分片,造成資源浪費,同時會影響查詢性能
集群健康狀況,包括以下三種: green健康狀態,指所有主副分片都正常分配; yellow指所有主分片都正常分配,但是有副本分片未正常分配; red表示有主分片未分配
我們可以通過這個api查看集群的狀態信息: GET _cluster/health
我們也可以通過cerebro或者head插件來直接獲取當前集群的狀態
需要注意的是,即使當前集群的狀態為 red ,也並不代表當前的ES喪失了提供服務的能力。只是說未被分配主分片的索引無法正常存儲和操作而已。
這里故障轉移的意思是,當ES集群出現某個或者多個節點宕機的情況,ES實現服務可用性的應對策略。
這里我們新建一個分片為3,副本為1的索引,分片分別分布在三個節點,此時集群為 green
當master節點所在機器宕機導致服務終止,此時集群會如何處理呢?
我們可以看到,從node1主節點宕機到ES恢復集群可用性的過程中,ES有著自己的故障轉移機制,保障了集群的高可用性。我們也可以在自己的本地上去進行試驗,建好索引後,kill掉主節點,觀察集群狀態就行。
同時,此時就算node2宕機了,那麼node3也能夠很快的恢復服務的提供能力。
我們知道,我們創建的文檔最終會存儲在分片上,那麼在分布式集群的基礎上,ES集群是怎麼判斷當前該文檔最終應該落在哪一個分片上呢?
很顯然,我們需要一個可以實現文檔均勻分布到各個分片上的映射演算法,那麼常見的隨機演算法和round-robin(輪詢)演算法可以滿足需要嗎?答案是不可以,這兩個演算法雖然可以實現文檔均勻分布分片的存儲需要,但是當我們通過 DocumentId 查詢文檔時,ES並不能知道這個文檔ID到底存儲在了哪個節點的分片上,所以只能夠從所有分片上檢索,時間長。如果我們為這個問題建立一個文檔和分片映射關系的表,雖然確實可以快速定位到文檔對應的存儲分片,但是當文檔的數據量很大的時候,那麼檢索的效率也會隨之變低。
對於上面這個問題,ES提供的解決方法是 建立文檔到分片的映射演算法
es 通過如下的公式計算文檔對應的分片:
hash演算法 保證可以將數據均勻地分散在分片中
routing 是一個關鍵參數,默認是文檔id,也可以自行指定
number_of_primary_shards 是主分片數
我們可以看到,該演算法與主分片數相關, 這也是分片數一旦確定後便不能更改的原因
我們已經知道了ES是如何將文檔映射到分片上去了,下面我們就來詳細講解一下文檔創建、讀取的流程。
腦裂問題,英文為 split-brain ,是分布式系統中的經典網路問題,如下圖所示:
3個節點組成的集群,突然node1的網路和其他兩個節點中斷
解決方案為 僅在可選舉master-eligible節點數大於等於quorum時才可以進行master選舉
在講文檔搜索實時性之前,先講一下倒排索引的不可變更特性。由於倒排索引一旦生成,不可變更的特定,使得其有著以下3點好處:
下面,將針對Lucene實現文檔實時性搜索的幾個動作進行講解,分析其是如何在新增文檔後實現ES的搜索實時性的。
我們從上面的描述中知道,當我們新增了一個文檔後會新增一個倒排索引文件 segment ,但是 segment 寫入磁碟的時間依然比較耗時(難以實現實時性),所以ES藉助文件系統緩存的特性, 先將 segment 在緩存中創建並開放查詢來進一步提升實時性 ,該過程在es中被稱為refresh。
在refresh之前文檔會先存儲在一個buffer中,refresh時將 buffer中的所有文檔清空並生成 segment
es默認每1秒執行一次refresh,因此文檔的實時性被提高到1秒 ,這也是es被稱為近實時(Near Real Time)的原因
reflush雖然通過 將文檔存放在緩存中 的方式實現了秒級別的實時性,但是如果在內存中的segment還沒有寫入磁碟前發生了宕機,那麼其中的文檔就無法恢復了,如何解決這個問題呢?
ES 引入 translog 機制。寫入文檔到 buffer 時,同時將該操作寫入 translog 中。
translog文件會即時寫入磁碟(fsync),在ES 6.x中,默認每個請求都會落盤,我們也可以修改為每5秒寫一次,這樣風險便是丟失5秒內的數據,相關配置為index.translog.*。同時ES每次啟動時會檢查translog 文件,並從中恢復數據。
flush 負責將內存中的segment寫入磁碟,主要做如下的工作:
Reflush和Flush執行的時機
ES的做法是 首先刪除文檔,然後再創建新文檔
我們上面提到,新增文檔是通過新建segment來解決,刪除文檔是通過維護.del文件來進行的,假如現在我們設置的 reflush 時間間隔為1秒,那麼一小時單個ES索引就會生成3600個segment,一天下來乃至一個月下來會產生的segment文件數量更是不可想像。為了解決Segment過多可能引起的性能下降問題,ES中採用了Segment Merging(即segment合並)的方法來減少segment的數量。
執行合並操作的方式有兩種,一種是ES定時在後台進行 Segment Merging 操作,還有一種是我們手動執行 force_merge_api 命令來實現合並操作。