华章计算机 2017-05-02 16:08:00 浏览2068 评论0
摘要: 本节书摘来自华章计算机《深入理解ElasticSearch》一书中的第3章,第3.6节,作者:[美] 拉斐尔·酷奇(Rafa Ku) 马雷克·罗戈任斯基(Marek Rogoziński)更多章节内容可以访问云栖社区“华章计算机”公众号查看。
本节书摘来自华章计算机《深入理解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(默认)
前面提到的每一种段合并策略都有各自的参数,而这些参数定义了各自的行为特点,并且它们的默认值都是可以覆写的(请阅读后续章节来了解这些参数)。
为了告知ElasticSearch我们想使用的段合并策略,可以将配置文件的index.merge.policy.type字段配置成我们期望的段合并策略类型。例如下面这样:
一旦使用特定的段合并策略创建了索引,它就不能被改变。但是,可以使用索引更新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合并策略时,可配置以下这些选项:
配置log byte size合并策略
当采用log_byte_size合并策略时,可配置以下选项:
当使用log_doc(文档数对数)合并策略时,可配置以下这些选项:
与前面介绍的合并策略类似,上面提及的属性需要以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属性来实现。一般来说,可以按如下公式来计算允许的最大线程数:
如果我们的系统是8核的,那么调度器允许的最大线程数可以设置为4。
顺序合并调度器
该调度器非常简单,它使用同一个线程执行所有的索引合并操作。在执行合并时,该线程的其他文档处理都会被挂起,从而索引操作会延迟进行。
设置合并调度
为了设置特定的索引合并调度器,用户可将index.merge.scheduler.type的属性值设置为concurrent或serial。例如,为了使用并发合并调度器,用户应该如此设置:
如果想使用顺序合并调度器,用户则应该像下面这样设置:
https://yqfile.alicdn.com/afabd2dd212ca25d83555cb9681cd9f307348656.png" >