Elasticsearch 分片交互過程分析

jopen 8年前發布 | 10K 次閱讀 ElasticSearch 搜索引擎 Elastic Search

出處:http://www.iteye.com

一、Elasticseach如何將數據存儲到分片中

問題:當我們要在ES中存儲數據的時候,數據應該存儲在主分片和復制分片中的哪一個中去;當我們在ES中檢索數據的時候,又是怎么判斷要查詢的數據是屬于哪一個分片。

  • 數據存儲到分片的過程是一定規則的,并不是隨機發生的。

  • 規則:shard = hash(routing) % number_of_primary_shards

  • Routing值可以是一個任意的字符串,默認情況下,它的值為存數數據對應文檔 _id 值,也可以是用戶自定義的值。Routing這個字符串通過一個hash的函數處理,并返回一個數值,然后再除以索引中主分片的數目,所得的余數作為主分片的編號,取值一般在0到number_of_primary_shards - 1的這個范圍中。通過這種方法計算出該數據是存儲到哪個分片中。

  • 正是這種路由機制,導致了主分片的個數為什么在索引建立之后不能修改。對已有索引主分片數目的修改直接會導致路由規則出現嚴重問題,部分數據將無法被檢索。

二、主分片與復制分片如何交互

為了說明這個問題,我用一個例子來說明。

在上面這個例子中,有三個ES的node,其中每一個index中包含兩個primary shard,每個primary shard擁有一個replica shard。下面從幾種常見的數據操作來說明二者之間的交互情況。

1、索引與刪除一個文檔

這兩種過程均可以分為三個過程來描述:

階段1:客戶端發送了一個索引或者刪除的請求給node 1。

階段2:node 1通過請求中文檔的 _id 值判斷出該文檔應該被存儲在shard 0 這個分片中,并且node 1知道shard 0的primary shard位于node 3這個節點上。因此node 1會把這個請求轉發到node 3。

階段3:node 3在shard 0 的primary shard上執行請求。如果請求執行成功,它node 3將并行地將該請求發給shard 0的其余所有replica shard上,也就是存在于node 1和node 2中的replica shard。如果所有的replica shard都成功地執行了請求,那么將會向node 3回復一個成功確認,當node 3收到了所有replica shard的確認信息后,則最后向用戶返回一個Success的消息。

2、更新一個文檔

該過程可以分為四個階段來描述:

階段1:客戶端向node 1發送一個文檔更新的請求。

階段2:同樣的node 1通過請求中文檔的 _id 值判斷出該文檔應該被存儲在shard 0 這個分片中,并且node 1知道shard 0的primary shard位于node 3這個節點上。因此node 1會把這個請求轉發到node 3。

階段3:node 3從文檔所在的primary shard中獲取到它的JSON文件,并修改其中的_source中的內容,之后再重新索引該文檔到其primary shard中。

階段4:如果node 3成功地更新了文檔,node 3將會把文檔新的版本并行地發給其余所有的replica shard所在node中。這些node也同樣重新索引新版本的文檔,執行后則向node 3確認成功,當node 3接收到所有的成功確認之后,再向客戶端發送一個更新成功的信息。

3、檢索文檔

CRUD這些操作的過程中一般都是結合一些唯一的標記例如:_index,_type,以及routing的值,這就意味在執行操作的時候都是確切的知道文檔在集群中的哪個node中,哪個shard中。

而檢索過程往往需要更多的執行模式,因為我們并不清楚所要檢索的文檔具體位置所在, 它們可能存在于ES集群中個任何位置。因此,一般情況下,檢索的執行不得不去詢問index中的每一個shard。

但是,找到所有匹配檢索的文檔僅僅只是檢索過程的一半,在向客戶端返回一個結果列表之前,必須將各個shard發回的小片的檢索結果,拼接成一個大的已排好序的匯總結果列表。正因為這個原因,檢索的過程將分為查詢階段與獲取階段(Query Phase and Fetch Phase)。

  • Query Phase

在最初的查詢過程中,查詢請求會廣播到index中的每一個primary shard和replica shard中,每一個shard會在本地執行檢索,并建立一個優先級隊列(priority queue)。這個優先級隊列是一個根據文檔匹配度這個指標所排序列表,列表的長度由分頁參數from和size兩個參數所決定。例如:

下面從一個例子中說明這個過程:

Query Phase階段可以再細分成3個小的子階段:

子階段1:客戶端發送一個檢索的請求給node 3,此時node 3會創建一個空的優先級隊列并且配置好分頁參數from與size。

子階段2:node 3將檢索請求發送給該index中個每一個shard(這里的每一個意思是無論它是primary還是replica,它們的組合可以構成一個完整的index數據)。每個shard在本地執行檢索,并將結果添加到本地優先級隊列中。

子階段3:每個shard返回本地優先級序列中所記錄的_id與sort值,并發送node 3。Node 3將這些值合并到自己的本地的優先級隊列中,并做全局的排序。

  • Fetch Phase

Query Phase主要定位了所要檢索數據的具體位置,但是我們還必須取回它們才能完成整個檢索過程。而Fetch Phase階段的任務就是將這些定位好的數據內容取回并返回給客戶端。

同樣也用一個例子來說明這個過程:

Fetch Phase過程可以分為三個子過程來描述:

子階段1:node 3獲取了所有待檢索數據的定位之后,發送一個mget的請求給與數據相關的shard。

子階段2:每個收到node 3的get請求的shard將讀取相關文檔_source中的內容,并將它們返回給node 3。

子階段3:當node 3獲取到了所有shard返回的文檔后,node 3將它們合并成一條匯總的結果,返回給客戶端。

http://my.oschina.net/galenz/blog/422189

已有 0 人發表留言,猛擊->> 這里 <<-參與討論

ITeye推薦

來自: http://itindex.net/detail/55051-elasticsearch-交互-分析

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!