elasticsearch 執行分布式檢索 九

2021-10-07 00:07:49 字數 4383 閱讀 1413

乙個 crud 操作只對單個文件進行處理,文件的唯一性由_index, _type, 和 routing values(通常預設是該文件的 _id )的組合來確定。 這表示我們確切的知道集群中哪個分片含有此文件。

但是找到所有的匹配文件僅僅完成事情的一半。 在 search 介面返回乙個 page 結果之前,多分片中的結果必須組合成單個排序列表。 為此,搜尋被執行成乙個兩階段過程,我們稱之為query then fetch

在初始 查詢階段 時, 查詢會廣播到索引中每乙個分片拷貝(主分片或者副本分片)。 每個分片在本地執行搜尋並構建乙個匹配文件的 優先佇列。

優先佇列

乙個 優先佇列 僅僅是乙個存有 top-n 匹配文件的有序列表。優先佇列的大小取決於分頁引數 from 和 size 。例如,如下搜尋請求將需要足夠大的優先佇列來放入100條文件。

get /_search

這個查詢階段的過程如圖所示:

查詢階段包含以下三個步驟:

當乙個搜尋請求被傳送到某個節點時,這個節點就變成了協調節點。 這個節點的任務是廣播查詢請求到所有相關分片並將它們的響應整合成全域性排序後的結果集合,這個結果集合會返回給客戶端。

第一步是廣播請求到索引中每乙個節點的分片拷貝。 查詢請求可以被某個主分片或某個副本分片處理, 這就是為什麼更多的副本(當結合更多的硬體)能夠增加搜尋吞吐率。 協調節點將在之後的請求中輪詢所有的分片拷貝來分攤負載。

每個分片在本地執行查詢請求並且建立乙個長度為 from + size 的優先佇列—也就是說,每個分片建立的結果集足夠大,均可以滿足全域性的搜尋請求。 分片返回乙個輕量級的結果列表到協調節點,它僅包含文件 id 集合以及任何排序需要用到的值,例如 _score 。

協調節點將這些分片級的結果合併到自己的有序優先佇列裡,它代表了全域性排序結果集合。至此查詢過程結束。

乙個索引可以由乙個或幾個主分片組成, 所以乙個針對單個索引的搜尋請求需要能夠把來

自多個分片的結果組合起來。 針對 multiple 或者 all 索引的搜尋工作方式也是完全一致的

—​僅僅是包含了更多的分片而已。

查詢階段標識哪些文件滿足搜尋請求,然後需要取回這些文件。這是取回階段的任務:

分布式階段由以下步驟構成:

協調節點首先決定哪些文件 確實 需要被取回。例如,如果我們的查詢指定了 ,最初的90個結果會被丟棄,只有從第91個開始的10個結果需要被取回。這些文件可能來自和最初搜尋請求有關的乙個、多個甚至全部分片。

協調節點給持有相關文件的每個分片建立乙個 multi-get request ,並傳送請求給同樣處理查詢階段的分片副本。

分片載入文件體-- _source 字段—​如果有需要,用元資料和 search snippet highlighting 豐富結果文件。 一旦協調節點接收到所有的結果文件,它就組裝這些結果為單個響應返回給客戶端。

深分頁(deep pagination)

先查後取的過程支援用 from 和 size 引數分頁,但是這是 有限制的 。 要記住需要傳遞資訊給協調節點的每個分片必須先建立乙個 from + size 長度的佇列,協調節點需要根據 number_of_shards * (from + size) 排序文件,來找到被包含在 size 裡的文件。

取決於你的文件的大小,分片的數量和你使用的硬體,給 10,000 到 50,000 的結果文件深分頁( 1,000 到 5,000 頁)是完全可行的。但是使用足夠大的 from 值,排序過程可能會變得非常沉重,使用大量的cpu、記憶體和頻寬。因為這個原因強烈建議不要使用深分頁。

實際上, 「深分頁」 很少符合人的行為。當2到3頁過去以後,人會停止翻頁,並且改變搜尋標準。

如果你 確實 需要從你的集群取回大量的文件,你可以通過用 scroll 查詢禁用排序使這個取回行為更有效率;

有幾個 查詢引數可以影響搜尋過程:

偏好這個引數 preference 允許 用來控制由哪些分片或節點來處理搜尋請求。 它接受像 _primary, _primary_first, _local, _only_node:xyz, _prefer_node:xyz, 和 _shards:2,3 這樣的值,

但是最有用的值是某些隨機字串,它可以避免 bouncing results 問題。

bouncing results

想象一下有兩個文件有同樣值的時間戳字段,搜尋結果用 timestamp 欄位來排序。 由於搜

索請求是在所有有效的分片副本間輪詢的,那就有可能發生主分片處理請求時,這兩個文

檔是一種順序, 而副本分片處理請求時又是另一種順序。

這就是所謂的 bouncing results 問題: 每次使用者重新整理頁面,搜尋結果表現是不同的順序。

讓同乙個使用者始終使用同乙個分片,這樣可以避免這種問題, 可以設定 preference 引數

為乙個特定的任意值比如使用者會話id來解決。

通常分片處理完它所有的資料後再把結果返回給協同節點,協同節點把收到的所有結果合併為最終結果。

這意味著花費的時間是最慢分片的處理時間加結果合併的時間。如果有乙個節點有問題,就會導致所有的響應緩慢。

引數 timeout 告訴 分片允許處理資料的最大時間。如果沒有足夠的時間處理所有資料,這個分片的結果可以是部分的,甚至是空資料。

搜尋的返回結果會用屬性 timed_out 標明分片是否返回的是部分結果:

...

"timed_out"

: true, //這個搜尋請求超時了

...

在 路由乙個文件到乙個分片中定製引數 routing ,它能夠在索引時提供來確保相關的文件,比如屬於某個使用者的文件被儲存在某個分片上。 在搜尋的時候,不用搜尋索引的所有分片,而是通過指定幾個 routing 值來限定只搜尋幾個相關的分片:

get /_search?routing=user_1,user2
get /_search?search_type=dfs_query_then_fetch
搜尋型別 dfs_query_then_fetch 有預查詢階段,這個階段可以從所有相關分片獲取詞頻來計算全域性詞頻。

scroll 查詢 可以用來對 elasticsearch 有效地執行大批量的文件查詢,而又不用付出深度分頁那種代價。

游標查詢允許我們 先做查詢初始化,然後再批量地拉取結果。 這有點兒像傳統資料庫中的 cursor 。

游標查詢會取某個時間點的快照資料。 查詢初始化之後索引上的任何變化會被它忽略。 它通過儲存舊的資料檔案來實現這個特性,結果就像保留初始化時的索引 檢視 一樣。

深度分頁的代價根源是結果集全域性排序,如果去掉全域性排序的特性的話查詢結果的成本就會很低。 游標查詢用字段 _doc 來排序。 這個指令讓 elasticsearch 僅僅從還有結果的分片返回下一批結果。

啟用游標查詢可以通過在查詢的時候設定引數 scroll 的值為我們期望的游標查詢的過期時間。 游標查詢的過期時間會在每次做查詢的時候重新整理,所以這個時間只需要足夠處理當前批的結果就可以了,而不是處理查詢結果的所有文件的所需時間。 這個過期時間的引數很重要,因為保持這個游標查詢視窗需要消耗資源,所以我們期望如果不再需要維護這種資源就該早點兒釋放掉。 設定這個超時能夠讓 elasticsearch 在稍後空閒的時候自動釋放這部分資源。

get /old_index/_search?scroll=1m  //保持游標查詢視窗一分鐘。

}, "sort":[

"_doc"

], //關鍵字 _doc 是最有效的排序順序。

"size"

: 1000

}

下面這個查詢的返回結果包括乙個字段 _scroll_id, 它是乙個base64編碼的長字串 。 現在我們能傳遞字段 _scroll_id 到 _search/scroll 查詢介面獲取下一批結果:

get /_search/scroll

這個游標查詢返回的下一批結果。 儘管我們指定字段 size 的值為1000,我們有可能取到超過這個值數量的文件。 當查詢的時候, 字段 size 作用於單個分片,所以每個批次實際返回的文件數量最大為size * number_of_primary_shards

注意游標查詢每次返回乙個新字段 _scroll_id。每次我們做下一次游標查詢, 我們必須把

前一次查詢返回的字段 _scroll_id 傳遞進去。 當沒有更多的結果返回的時候,我們就處理

完所有匹配的文件了。

Elasticsearch 執行架構詳解

檔案系統 hdfs,資料庫 hbase,訊息佇列 kafka,協調服務 zookeeper,接下來要讓大資料儲存的生態圈變得更完整,不得不提的就是搜尋引擎了,雖然說 elasticsearch 是以搜尋聞名的,但是說到底它還是個資料庫,它底層的儲存特性使它擁有了毫秒級的全文檢索響應能力,很好地補充了...

ElasticSearch安裝及執行的坑

寫文章 sam dragon 發表於cnblogs訂閱 158 2.用 tar zxvf 解壓包 3.增加乙個elk使用者,elasticsearch7不可用root使用者執行 4.新建使用者必須要用 chown r 使用者名稱 資料夾 進行許可權分配 1 max file descriptors ...

elasticsearch配置詳解

elasticsearch的config資料夾裡面有兩個配置檔案 elasticsearch.yml和logging.yml,第乙個是es的基本配置檔案,第二個是日誌配置檔案,es也是使用log4j來記錄日誌的,所以logging.yml裡的設定按普通log4j配置檔案來設定就行了。下面主要講解下e...