當前位置:
首頁 > 知識 > ElasticSearch數據副本模型

ElasticSearch數據副本模型

介紹

ES裡面的每一個索引(Index)由多個shard組成,每一個shard有多個副本。這些副本被稱為同步組。當增加或者刪除文檔時,這些副本之間必須保持同步,以便讓所有副本都能包含相同的文檔。如果同步失敗,有可能會導致從一個副本讀的結果和從另外一個副本上讀的結果不一致。在shard的所有副本之間保持數據同步並同時對外提供一致的讀服務,我們這樣的處理過程稱之為「數據副本模型。

ES的「數據複製模型」是一種「主-備」式的模型,這種模型在微軟的研究論文中有專門的介紹。基於這種模型,「同步組 的所有副本中間會有一個專門的「Primary shard」角色,除了」Primary shard「之外的其餘副本都被稱為」replica shard「。 Primary shard是所有文檔的索引操作(文檔寫操作)的入口點, 其負責索引操作的校驗,確保這些索引操作是正確且合法的。當索引操作校驗通過後, primary shard會負責把索引操作複製並傳遞給replica shard,讓「同步組」裡面所有副本會進行相同的寫操作,進而保持所有副本上包含的文檔是一致的。

基本寫模型

根據文檔的doc ID,ES首先會識別出來一個文檔的索引操作應該由哪個「同步組」來執行,這個「同步組」也就是存儲該文檔的目的容器。在「同步組被識別出來後,該文檔的索引操作就被傳遞給「同步組」中的當前primary shard。Primary shard 負責校驗並傳遞同樣的文檔索引操作給其他的relica shard。因為replica shard有可能會因為各種可能原因造成離線,所以ES並不要求primary shard一定要複製操作給所有的replica shard。事實上,primary shard維護了一個可以接收索引操作的replica shard列表。這個列表被稱為「in-sync 副本列表」, 列表數據由master node來維護。 primary shard需要把文檔的索引操作複製傳遞給in-sync列表中每一個relica shard。

下面是primary shard處理的基本流程:

校驗操作請求,如果有結構類的錯誤(例如,object filed 卻存儲了一個數字),就拒絕此請求

如果校驗通過,本地先執行索引操作,例如索引或者刪除文檔。在本地操作過程中,也會做一些校驗,如果校驗失敗(例如keyword欄位的值太長,超過Lucene索引長度限制),也會拒絕請求。

轉發索引操作給當前in-sync裡面的所有replica shard。如果有多個replica shard,轉發操作會並行來執行

當所有replica 都成功執行了和本地一樣的索引操作,並且給primary shard 發回了成功確認,primary shard 就會發成功確認給客戶端。

異常處理

在執行索引操作的過程中,每一步都可能會出現問題,比如磁碟壞了、node down掉了、node之間網路不通了、或者配置錯誤了等等,也許會導致索引操作在primary shard執行成功,在一個或者多個replica shard 卻執行失敗了。這些都是失敗的情況,雖然並不是經常出現,但是primary shard必須處理各種異常的情況。

一種場景是primary shard自己出問題了,在這種情況下 ,primary shard 所在的node會發消息給master node告知這種異常情況出現了 。索引操作會等待master node選出新的primary shard並把索引操作轉發給新的primary shard。當然這種等待不是無限期的,預設會等待1分鐘。當然master node也不是被動等待通知,master node會主動持續監測node的健康狀態,並根據健康狀態來決定是否選出新的primary shard。一種典型的情況就是當primary shard所在node 網路不通的時候,master node會認為 primary shard所在node可能down死掉了,就會選出新的primary shard,並更新in-sync 列表。

另外一種場景就是索引操作在primary shard上執行成功,但是在replica shard執行卻失敗了。當然被定義失敗的各種情況有很多,比如索引操作在replica上的確失敗了(比如replica shard所在硬碟出問題了)、primary shard和replica shard之間網路原因導致索引操作請求沒有到達replica shard、或者primary shard沒有收到replica shard的成功確認等等。這些複雜的情況導致的共同結果就是:primary shard 沒有收到in-sync列表裡面的所有replica shard的索引操作成功確認。為了解決這樣的問題,primary shard 會發消息給master node ,請求master node 刪除出問題的replica shard。當primary shard 收到master node 成功刪除問題replica shard的確認消息時,primary shard會發索引操作成功確認給客戶端。要注意的是,master node同時會通知另外一個node會構建一個新的replica shard,以保證系統處在一個健康狀態。

當轉發操作請求給replica shards的時候,primary shard會根據replica shard的響應情況來確認自己仍然是活躍的primary shard。某些情況下,因為網路原因,primary shard 也許已經被master node給降級了,但是primary shard還沒收到這種降級通知,所以其會繼續處理進來的索引操作請求。當老的primary shard把索引操作請求轉發給其他replica shard時,replica shard發現請求來自於一個已經不合法的primary shard,就會拒絕請求並發響應給這個不合法的primary shard。當這個不合法的primary shard收到拒絕的響應時候,就會和master node聯繫,獲取最新的狀態信息。在從master node發回的信息中,老的primary shard發現自己已經被推翻,就會把索引操作請求轉發給新的primary shard。

沒有replica shard時,情況會怎麼樣?

因為各種原因,所有的replica shards可能都會失效。在這種情況下,primary 會自己處理索引操作,而不會等待任何外部的確認(因為沒有replica shards了)。看起來似乎有點怪怪的,這主要是因為primary shards不能自己定義而只能依賴master nodereplica shards是否失敗。這就意味著,master node知道primary shards 是唯一的正常能工作的副本。我們要保證master node不會把其他任何過期的shard 副本定義成新的primary,也保證發到primary shard的索引操作請求不會丟失。但是不可否認,primary shard上的物理硬體出問題了,肯定也會導致數據丟失。

基本讀模型

ES中的讀可以是通過ID的輕量級查找,也可以是重量級的非常消耗CPU的複雜聚合計算。ES的「主-備」模型的優雅之處在於它保持所有副本的數據一致的,這樣「同步組」中的任何單個副本都可以對外提供讀服務。

當集群中的一個node收到讀請求時,該node負責轉發讀請求給相關的shards、聚合shards的響應並把響應發送給客戶端。我們這樣的node稱之為本次請求的協調node。協調node上的基本讀的處理流程如下:

根據請求,解析出來要轉發的「同步組」。多數搜索需要查詢多個「同步組,每個同步組」是可能包含了搜索結果的一部分數據。但是如果是根據id檢索一個文檔,可以根據routing演算法,計算出一個包含該文檔的「同步組」。

從每一個要轉發「同步組」裡面選出一個活躍的shard。這個shard可以是primary,也可以是replica。預設情況下,ES使用round robin的策略在「同步組裡面選擇shard。

把請求轉發給選出來的shards

合併各個shard的響應並發響應給客戶端。要注意的是,如果根據id檢索文檔,因為轉發shard是一個,所以就不存在合併的過程了。

異常處理

當一個shard沒有成功執行讀請求、轉發響應給協調node時,協調node會從該shard所在的」同步組「中選擇另外一個shard,然後把讀請求轉發給它。重複性的「失敗-選擇」可能會導致最後「同步組裡面沒有shard 可用。在某些情況下,ES更青睞快速響應,而不是搜索結果的完整性,例如_search。即使缺失了部分查詢結果,ES也希望能快速響應給客戶端,而不是等待問題解決(搜索結果是否完整會在響應頭有體現)。

一些優雅的點

基本讀、基本寫流程定義了ES作為一個系統,是如何支持讀和寫操作的。但是實踐中,讀寫操作可能是同時並發執行的,所以讀、寫流程是相互影響的。此模型有一些優雅的點,如下:

高效讀

正常情況下,每次讀請求操作只會被「同步組」裡面shard執行一次。在異常情況下,有可能會出現「同步組」裡面的多個shard執行了多次讀操作,例如協調node在shard沒有響應的情況下,會重新選擇另外一個shard,再次發出讀請求操作。

未確認讀

因為primary shard首先在本地執行索引操作,然後才轉發索引操作給replica shard。在索引操作完全確認之前,primary shard執行了一個讀請求操作,就能讀到還沒確認的數據。

預設兩個副本

在一些基於投票的系統中,要實現容錯,有可能最少需要的副本數是3. 但是基於ES的模型,僅維護兩個副本,就可以實現容錯。

失敗

失敗的時候,會出現下面可能的情況:

單個shard有可能會讓索引操作執行的更慢

因為primary shard需要等待in-sync裡面所有replica shard執行完並響應才能發確認給客戶端,所以任何一個處理慢的shard都會拉低本次索引操作的處理速度。這是為了實現前面提到的高效讀而付出的成本代價。當然,單個慢的shard也會拉低路由到此shard上的讀請求操作處理速度,進而影響那次search(因為search是由多個shard的讀請求組成)。

臟讀

一個孤立的primary shard可能會暴露將不會被確認的但是已經被寫到本地的數據。這是因為孤立的primary只有在發索引操作請求給replica或者跟master node時才能知道自己已經被孤立了。因為數據已經被寫入本地了,如果此時有讀請求過來,讀請求就可能會讀到剛剛已經寫進去的數據。為了降低這種風險,primary 會定期(預設每1秒)ping master node,如果發現已經找不到master了,就會拒絕索引操作。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 千鋒JAVA開發學院 的精彩文章:

TAG:千鋒JAVA開發學院 |