天天看點

《深入了解ElasticSearch》——3.6 控制索引合并

本節書摘來自華章計算機《深入了解elasticsearch》一書中的第3章,第3.6節,作者:[美] 拉斐爾·酷奇(rafa ku) 馬雷克·羅戈任斯基(marek rogoziński)更多章節内容可以通路雲栖社群“華章計算機”公衆号檢視。

讀者知道(我們已經在第1章中讨論過),在elasticsearch中每個索引都會建立一到多個分片以及零到多個副本,也知道這些分片或副本本質上都是lucene索引,而lucene索引又基于多個索引段建構(至少一個索引段)。索引檔案中絕大部分資料都是隻寫一次,讀多次,而隻有用于儲存文檔删除資訊的檔案才會被多次更改。在某些時刻,當某種條件滿足時,多個索引段會被拷貝合并到一個更大的索引段,而那些舊的索引段會被抛棄并從磁盤中删除,這個操作稱為段合并(segment merging)。

也許你會有疑問,為什麼非要進行段合并?這是因為:首先,索引段的個數越多,搜尋性能越低且耗費記憶體更多。另外,索引段是不可變的,因而實體上你并不能從中删除資訊。也許你碰巧從索引中删除了大量文檔,但這些文檔隻是做了删除标記,實體上并沒有被删除。而當段合并發生時,這些标記為删除的文檔并沒有複制到新的索引段中。如此一來,這減少了最終索引段中的文檔數。

頻繁的文檔更改操作會導緻大量的小索引段,進而導緻檔案句柄打開過多的問題。我們必須要對這種情況有所準備,如修改系統配置,或設定合适的最大檔案打開數。

從使用者角度來看,段合并可快速概括為如下兩個方面:

當多個索引段合并為一個的時候,會減少索引段的數量并提高搜尋速度。

同時也會減少索引的容量(文檔數),因為在段合并時會移除被标記為已删除的那些文檔。

盡管段合并有這些好處,但使用者也應該了解到段合并的代價,即主要是i/o操作的代價。在速度較慢的系統中,段合并會顯著影響性能。基于這個原因,elasticsearch允許使用者選擇段合并政策(merge policy)及存儲級節流(store level throttling)。本章後續部分将會讨論段合并政策,而存儲級節流則安排在6.2節中讨論。

3.6.1 選擇正确的合并政策

盡管段合并是lucene的責任,elasticsearch也允許使用者配置想用的段合并政策。到目前為止,有三種可用的合并政策:

tiered(預設)

log_byte_size

log_doc

前面提到的每一種段合并政策都有各自的參數,而這些參數定義了各自的行為特點,并且它們的預設值都是可以覆寫的(請閱讀後續章節來了解這些參數)。

為了告知elasticsearch我們想使用的段合并政策,可以将配置檔案的index.merge.policy.type字段配置成我們期望的段合并政策類型。例如下面這樣:

《深入了解ElasticSearch》——3.6 控制索引合并

一旦使用特定的段合并政策建立了索引,它就不能被改變。但是,可以使用索引更新api來改變該段合并政策的參數值。

接下來我們來了解這些不同的段合并政策,以及它們提供的功能,并讨論這些段合并政策的具體配置。

tiered合并政策

這是elasticsearch的預設選項。它能合并大小相似的索引段,并考慮每層允許的索引段的最大個數。讀者需要清楚單次可合并的索引段的個數與每層允許的索引段數的差別。在索引期,該合并政策會計算索引中允許出現的索引段個數,該數值稱為門檻值(budget)。如果正在建構的索引中的段數超過了門檻值,該政策将先對索引段按容量降序排序(這裡考慮了被标記為已删除的文檔),然後再選擇一個成本最低的合并。合并成本的計算方法傾向于回收更多删除文檔和産生更小的索引段。

如果某次合并産生的索引段的大小大于index.merge.policy.max_merged_segment參數值,則該合并政策會選擇更少的索引段參與合并,使得生成的索引段的大小小于門檻值。這意味着,對于有多個分片的索引,預設的index.merge.policy.max_merged_segment則顯得過小,會導緻大量索引段的建立,進而降低查詢速度。使用者應該根據自己具體的資料量,觀察索引段的狀況,不斷調整合并政策以滿足應用需求。

log byte size合并政策

該政策會不斷地以位元組數的對數為計算機關,選擇多個索引來合并建立新索引。合并過程中,時不時會出現一些較大的索引段,然後又産生出一些小于合并因子(merge factor)的索引段,如此循環往複。你可以想象,時而有一些相同數量級的索引段,其個數會變得比合并因子還少。當碰到一個特别大的索引段時,所有小于該級别的索引段都會被合并。索引中的索引段個數與下次用于計算的位元組數的對數成正比。是以,該合并政策能夠保持較少的索引段數量并且極小化段索引合并的代價。

log doc合并政策

該政策與log_byte_size合并政策類似,不同的是前者基于索引的位元組數計算,而後者基于索引段的文檔數計算。以下兩種情況中該合并政策表現良好:文檔集中的文檔大小類似或者你期望參與合并的索引段在文檔數方面相當。

3.6.2 合并政策配置

我們現在已經知道索引的段合并政策的工作原理了,隻是還缺乏配置方面的相關知識,是以現在就來讨論每種合并政策及其提供的配置選項。請記住,大多數情況下預設選項是夠用的,除非有特殊的需求才需要修改。

配置tiered合并政策

當使用tiered合并政策時,可配置以下這些選項:

index.merge.policy.expunge_deletes_allowed:預設值為10,該值用于确定被删除文檔的百分比,當執行expungedeletes時,該參數值用于确定索引段是否被合并。

index.merge.policy.floor_segment:該參數用于阻止頻繁重新整理微小索引段。小于該參數值的索引段由索引合并機制處理,并将這些索引段的大小作為該參數值。預設值為2mb。

index.merge.policy.max_merge_at_once:該參數确定了索引期單次合并涉及的索引段數量的上限,預設為10。該參數值較大時,也就能允許更多的索引段參與單次合并,隻是會消耗更多的i/o資源。

index.merge.policy.max_merge_at_once_explicit:該參數确定了索引優化(optimize)操作和expungedeletes操作能參與的索引段數量的上限,預設值為30。但該值對索引期參與合并的索引段數量的上限沒有影響。

index.merge.policy.max_merged_segment:該參數預設值為5gb,它确定了索引期單次合并中産生的索引段大小的上限。這是一個近似值,因為合并後産生的索引段的大小是通過累加參與合并的索引段的大小并減去被删除文檔的大小而得來的。

index.merge.policy.segments_per_tier:該參數确定了每層允許出現的索引段數量的上限。越小的參數值會導緻更少的索引段數量,這也意味着更多的合并操作以及更低的索引性能。預設值為10,建議設定為大于等于index.merge.policy.max_merge_at_once,否則你将遇到很多與索引合并以及性能相關的問題。

index.reclaim_deletes_weight:該參數值預設為2.0,它确定了索引合并操作中清除被删除文檔這個因素的權重。如果該參數設定為0.0,則清除被删除文檔對索引合并沒有影響。該值越高,則清除較多被删除文檔的合并會更受合并政策青睐。

index.compund_format:該參數類型為布爾型,它确定了索引是否存儲為複合檔案格式(compound format),預設值為false。如果設定為true,則lucene會将所有檔案存儲在一個檔案中。這樣設定有時能解決作業系統打開檔案處理器過多的問題,但是也會降低索引和搜尋的性能。

index.merge.async:該參數類型為布爾型,用來确定索引合并是否異步進行。預設為true。

index.merge.async_interval:當index.merge.async設定為true(是以合并是異步進行的),該參數值确定了兩次合并的時間間隔,預設值為1s。請記住,為了觸發真正的索引合并以及索引段數量縮減操作,該參數值應該保持為一個較小值。

配置log byte size合并政策

當采用log_byte_size合并政策時,可配置以下選項:

merge_factor:該參數确定了索引期間索引段以多大的頻率進行合并。該值越小,搜尋的速度越快,消耗的記憶體也越少,而代價則是更慢的索引速度。如果該值越大,情形則正好相反,即更快的索引速度(因為索引合并更少),搜尋速度更慢,消耗的記憶體更多。該參數預設為10,對于批量索引建構,可以設定較大的值,對于日常索引維護則可采用預設值。

min_merge_size:該參數定義了索引段可能的最小容量(段中所有檔案的位元組數)。如果索引段大小小于該參數值,且merge_factor參數值允許,則進行索引段合并。該參數預設值為1.6mb,它對于避免産生大量小索引段是非常有用的。然而,使用者應該記住,該參數值設定為較大值時,将會導緻較高的合并成本。

max_merge_size:該參數定義了允許參與合并的索引段的最大容量(以位元組為機關)。預設情況下,參數不做設定,因而在索引合并時對索引段大小沒有限制。

maxmergedocs:該參數定義了參與合并的索引段的最大文檔數。預設情況下,參數沒有設定,是以當索引合并時,對索引段沒有最大文檔數的限制。

calibrate_size_by_deletes:該參數為布爾值,如果設定為true,則段中被删除文檔的大小會用于索引段大小的計算。

index.compund_format:該參數為布爾值,它确定了索引檔案是否存儲為複合檔案格式,預設為false。可參考tiered合并政策配置中該選項的解釋。

配置log doc合并政策

當使用log_doc(文檔數對數)合并政策時,可配置以下這些選項:

merge_factor:與log_byte_size合并政策中該參數的作用相同,請參考前面的解釋。

min_merge_docs:該參數定義了最小索引段允許的最小文檔數。如果某索引段的文檔數低于該參數值,且merge_factor參數允許,就會執行索引合并。該參數預設值為1000,它對于避免産生大量小索引段是非常有用的。但是使用者需要記住,将該參數值設定過大會增大索引合并的代價。

max_merge_docs:該參數定義了可參與索引合并的索引段的最大文檔數。預設情況下,該參數沒有設定,因而對參與索引合并的索引段的最大文檔數沒有限制。

calibrate_size_by_deletes:該參數為布爾值,如果設定為true,則段中被删除文檔的大小會在計算索引段大小時考慮進去。

與前面介紹的合并政策類似,上面提及的屬性需要以index.merge.policy為字首。例如,要設定min_merge_docs屬性,則應該設定index.merge.policy.min_merge_docs屬性。

除此之外,log_doc合并政策支援index.merge.async和index.merge.async_interval屬性,就像tiered合并政策那樣。

3.6.3 排程

除了可以影響索引合并政策的行為之外,elasticsearch還允許我們定制合并政策的執行方式。索引合并排程器(scheduler)分為兩種,預設的是并發合并排程器concurrentmerge-scheduler。

并發合并排程器

該排程器使用多線程執行索引合并操作,其具體過程是:每次開啟一個新線程直到線程數達到上限,當達到線程數上限時,必須開啟新線程(因為需要進行新的段合并),那麼所有索引操作将被挂起,直到至少一個索引合并操作完成。

為了控制最大線程數,可以通過修改index.merge.scheduler.max_thread_count屬性來實作。一般來說,可以按如下公式來計算允許的最大線程數:

《深入了解ElasticSearch》——3.6 控制索引合并

如果我們的系統是8核的,那麼排程器允許的最大線程數可以設定為4。

順序合并排程器

該排程器非常簡單,它使用同一個線程執行所有的索引合并操作。在執行合并時,該線程的其他文檔處理都會被挂起,進而索引操作會延遲進行。

設定合并排程

為了設定特定的索引合并排程器,使用者可将index.merge.scheduler.type的屬性值設定為concurrent或serial。例如,為了使用并發合并排程器,使用者應該如此設定:

《深入了解ElasticSearch》——3.6 控制索引合并

如果想使用順序合并排程器,使用者則應該像下面這樣設定:

《深入了解ElasticSearch》——3.6 控制索引合并

https://yqfile.alicdn.com/afabd2dd212ca25d83555cb9681cd9f307348656.png" >

繼續閱讀