索引合并基本原理
(1)索引合并概念:故名思议就是多个索引执行合并。由于索引可以是目录基本索引,也可以segment基本索引。从而合并的时候,可以针对文件夹(多segment),也可以针对单文件夹里面的segment合并。
(2)索引合并的前提:待合并的索引结构是相同的,只是值不同。也就是segment的基本结构是相同的。而这是倒排索引的基本特征,默认就支持。
(3)索引合并的本质:基于老索引构建新索引。从而合并过程,既是磁盘2.5-3倍的峰值,也是内存的2.5-3的峰值。
(4)索引合并的策略:周期性合并(按小时、按天、按周合并等)、随机合并(触发合并条件就合并)、按文件夹合并、按segement段数量合并、按segment大小(或者复合索引大小)合并。
(5)索引合并服务类型:手动触发合并、定时合并。
(6)索引合并解决什么问题:解决碎片索引(子索引增多)、索引空洞(delete密集)、去全量
(7)索引合并实现:线性合并、并行合并
索引合并的两种选择
1. 基于segment合并
在lucene中,就是这种合并,并且是无须用户关注,索引在commit的时候会执行判断,是否需要合并子段。
合并过程是按照segment文档数,反应到合并因子上。eg 合并因子10,那么第一个segment doc=10,也是第一层级。当100个 doc构建了,也就是生成了10个segment(每个segement是 10个doc),合并成一个segment(100个doc),下一层合并需等待 10个 100个doc的 segment出现,也就是1000doc构建后触发。依次类推。
这种合并好处:无需用户关注,底层API自动完成。
坏处:越到后面,合并越慢。并且无法有效控制这种合并的行为。如果是白天、或者高峰请求期,一旦合并,对磁盘对内存都是巨大开销,影响稳定性、性能。
基于segment合并是磁盘+内存的过程,是索引重建(当然lucene支持只改segment info的 add索引形式的 伪合并),那么不落地,直接内存合并、优化就能提升性能。 这种segment自动合并,solr也提供了plugin形式,灵活选择合并策略。 一种有效的扩展就是:基于segment size,而不是默认的doc判断,根据真实磁盘文件大小来选择合并的段。 这样可以有效的控制子索引的数量以及目标索引体积的大小。
2. 基于子目录合并
在实际过程中,基于底层的segment合并,业务层往往选择子目录合并。 子目录合并有两种选择:待合并目录合并到指定目录,一种是待合并目录合并到新目录。 前者少一次copy、而后者能有效的实现合并失败、突然down机时, 索引完整性。当然,lucene api是支持合并失败的数据不加载(合并成功后才修改segment info,尽管存在脏数据,但是不会被加载) 子目录合并,比较适合周期性合并。例如每天合并、每周合并,选择低峰期。达到合并目的,又降低对性能的影响。 典型应用场景:主索引不动、子索引递增,定期合并子索引。避开全量、切换的压力
索引合并的注意事项
【1】 基于子目录合并,合并前,被合并索引添加标示,eg pending,合并存储的新目录标记kill。当合并结束后,被合并目录标示改为kill,新目录改为suc。这样加载pending、suc,pass kill
【2】合并后索引视图打开 如果是多线程合并,那么reopen成功后,才可以close之前的内容。
【3】合并不推荐在固定目录,最好是每次递增目录。写同一目录,不便于排查。
【4】合并时机选择在夜晚、结点低峰期。合并过程暂停消费数据,否则同一份子索引可能发生并发冲突。