【小資說庫】第13期 應用程序開發(fā)人員、DBA和DBMS開發(fā)人員的分工是怎樣的?
1517
2022-05-28
背景:
ES在做Segment合并的時候,根據(jù)寫入模式和數(shù)據(jù)量,通常會有幾倍到十幾倍的寫放大。此處寫放大的定義是:磁盤寫入數(shù)據(jù)總量/最終生成索引的大小。ES通常有兩種類型的合并:NatureMerge和ForceMerge。NatureMerge是ES為了提升查詢性能、回收刪除Doc,在后臺定期調度的merge操作。對索引的任何增刪改操作都有可能觸發(fā)NatureMerge。而ForceMerge是指在一次導入大批量數(shù)據(jù)后,由運維人員手動觸發(fā)的merge操作,目的是減少segment數(shù)量,提升查詢性能。ForceMerge由于是人工觸發(fā),通常預設當前無查詢流量,所以過程比較激進,例如默認會merge成一個segment。
ES Merge過程解析
ES Merge過程可以視為一個典型的生產(chǎn)者-消費者模式。首先由MergePolicy根據(jù)一系列算法生成一個MergeSpecification對象。其次由MergeScheduler 執(zhí)行這個MergeSpecification。
MergePolicy類圖如上所示,當前ES/Lucene的默認Merge策略是TieredMergePolicy。具體算法流程解析稍后給出。在基類中的findMerges/findForcedMerges分別對應前述的NatureMerge和ForceMerge過程。
MergeScheduler的類圖如上所示,ES/Lucene默認實現(xiàn)為ConcurrentMergeScheduler。在Lucene層面,如果用戶不想觸發(fā)Merge,可以把默認MergePolicy和MergeScheduler分別指定為NoMergePolicy和NoMergeScheduler。但是ES目前并不開放這個配置。
分層Nature合并:
在前文中提到ES/Lucene的默認merge策略是TieredMergePolicy,即分層Merge。注意此處層只是一個按Segment大小劃分的邏輯概念,在文件系統(tǒng)和ES架構中不同層的索引并無本質區(qū)別。分層Merge主流程主要分三步:
1.???? 根據(jù)分層算法和deletesPctAllowed配置推導出本次Merge完成后AllowedSegCount和AllowedDelCount。這兩個值是后續(xù)循環(huán)中止條件。分層算法的邏輯非常簡單:比如當前索引總量為20M,AllowedSegCount為10個(10*2M)。當前索引總量為220M,AllowedSegCount為20個(20M*10 + 2M*10)。依此類推。
2.???? 滑動窗口算法尋找OneMerge對象。如下圖所示:對候選Segments按大小排序,通過一個滑動窗口從左往右滑動。窗口包含的Segment數(shù)從1開始,最大不超過maxMergeAtOnce(默認10)。同時窗口內的SegmentSize總和不超過maxMergedSegmentByte(默認5G)。
3.???? 對第二步選出來的OneMerge對象進行打分(分數(shù)越低越優(yōu))。打分考慮如下三個因素,考慮權重依次降低:
a)???? 選中Segment的大小平均度,越平均越好
b)???? 選中Segment中可回收Doc的比率,越高越好。
c)????? 選中SegmentByte總和,越小越好
分層Force合并
由于Force合并是手工觸發(fā),并不考慮當前服務吞吐和延遲。所以策略比Nature合并簡單粗暴很多。
1.???? 首先看當前Segment總數(shù) 2.???? 如果上述條件不滿足,則依舊采用滑動窗口算法。但是和Nature合并相反,F(xiàn)orce合并是從右向左滑動。窗口的初始值為2,不超過maxMergeAtOnceExplicit,并且窗口內SegmentSize總和不超過maxMergedSegmentByte。 ConcurrentMergeScheduler執(zhí)行過程 ConcurrentMergeScheduler實際上是對一個后臺線程池的封裝。當設備硬件為傳統(tǒng)磁盤時,啟動1個線程。當年設備硬件為SSD固態(tài)硬盤時,啟動的線程數(shù)為max(1, min(4, core/2))。同時工作的MergeCount = ThreadCount + 5。ConcurrentMergeScheduler執(zhí)行流程如下圖所示: 由上圖可知,整個流程其實就是對線程池的調用,虛線部分表示這是一個線程池Push的異步操作,并不需要等待merge工作實際完成。整個Merge過程實際上分四步,分別是mergeInit,mergeMiddle,mergeSuccess和mergeFinish。實際干活的事情都在mergeMiddle中實現(xiàn)。MergeMiddle借助SegmentMerger封裝,對FieldInfo、倒排、正排等索引結構做依次Merge。Merge過程如下: Lucene借助Codec的抽象,將索引處理流程和索引數(shù)據(jù)結構解耦開。右邊是Merge流程,左邊是每個數(shù)據(jù)結構對應的Codec。Codec中包含輸入數(shù)據(jù)的Consumer/Producer。分別負責生成索引和讀取索引。 小結 由上文可知,整個Lucene索引Merge的流程并不復雜。通過Policy/Scheduler將索引合并的描述MergeSpecification的生成和執(zhí)行解耦。開發(fā)者可以根據(jù)自己的業(yè)務場景需要,自由靈活的組裝。而Merge的實際工作MergeMiddle主要依賴SegmentMerger類實現(xiàn)。 附錄1:ES/Lucene對Merge寫放大有影響的參數(shù) 參數(shù)名 含義 默認值 備注 max_merge_at_once 一次普通merge可以參與的segment數(shù)量 10 max_merge_at_once_explicit 一次forcemerge可以參與的segment數(shù)量 30 推薦適度調大,可降低寫放大。 max_merged_segment_bytes OneMerge產(chǎn)出的segment最大值 5G 對于小規(guī)模索引夠用,對于海量索引數(shù)據(jù)推薦調大。如調為0則不觸發(fā)Nature Merge 附錄2:參考文獻 Lucene-8.6源碼:https://github.com/apache/lucene-solr Lucene官方API文檔:https://lucene.apache.org/core/8_6_2/core/index.html Solar官方文檔: https://lucene.apache.org/solr/guide/8_6/ http://blog.mikemccandless.com/2011/02/visualizing-lucenes-segment-merges.html 云搜索服務 CSS
版權聲明:本文內容由網(wǎng)絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實的內容,請聯(lián)系我們jiasou666@gmail.com 處理,核實后本網(wǎng)站將在24小時內刪除侵權內容。