ElasticSearch学习总结(五):底层索引控制

本文主要总结底层索引控制的一些知识点

1. 底层存储目录(Store Directory)

该模块主要用来控制索引数据的读写方式,Lucene所有在磁盘上的操作都是通过store模块来处理的,目前系统中有4种store类型,默认情况下,Elasticsearch会更具操作环境选择一个最佳的类型。4种类型如下

  1. fs
    默认的配置。将根据操作环境选择最佳配置:

    • Windows 32bit上选择simplefs
    • 其他32bit系统上选择niofs
    • 64bit系统上选择mmapfs。
  2. simplefs:最简单的一种实现(基于Java中的RandomAccessFile),对于简单的应用,该store类型足够了,但是该种类型的瓶颈主要在多线程读写.对于负责的应用,性能会很糟糕。 在Elasticsearch中,通过使用基于NIO的store类型而不使用基于简单文件系统的store实现

  3. niofs:该store类型是基于java.nio包中的FileChannel类的实现,该类型允许多线程操作同一个文件,在多线程访问的时候,性能也不会下降。该类型不推荐在windows上使用(主要是因为java实现的bug)

  4. mmapfs:该类型通过将文件映射到内存(mmap)的方式将索引索引分片存储到文件系统上。 内存映射会占用进程中虚拟内存一部分的地址空间,占用的大小等于映射文件的大小。 在使用此课程之前,请确保您已经允许充足的虚拟地址空间。

类型的配置除了可以在elasticsearch.yml中配置,还可以在创建索引的时候指定,方式如下:

PUT /my_index
{
  "settings": {
    "index.store.type": "niofs"
  }
}

2. 准实时提交/更新

一个理想的搜索解决方案中,新索引的数据应该能立即搜索到。ElasticSearch给人的第一印象仿佛就是如此工作的,即使是在多服务器环境下,然而事实并非如此. 原因如下:

在索引期新文档会写入索引段。索引段是独立的Lucene索引,这意味着查询是可以与索引并行的,只是不时会有新增的索引段被添加到可被搜索的索引段集合之中。

一次提交并不足以保证新索引的数据能被搜索到,这是因为Lucene使用了一个叫作Searcher的抽象类来执行索引的读取。如果索引更新提交了,但Searcher实例并没有重新打开,那么它觉察不到新索引段的加入。Searcher重新打开的过程叫作刷新(refresh)。出于性能考虑,Lucene推迟了耗时的刷新,因此它不会在每次新增一个文档(或批量增加文档)的时候刷新,但Searcher会每秒刷新一次。这种刷新已经非常频繁了,然而有很多应用却需要更快的刷新频率。如果碰到这种状况,要么使用其他技术,要么审视需求是否合理。

ElasticSearch提供了两种机制来控制刷新的频率

  1. 临时强制刷新:
curl -XGET localhost:9200/test/refresh
  1. 配置文件配置:配置elasticsearch.xml 中的index.refresh_inverval

刷新操作是很耗资源的,因此刷新间隔时间越长,索引速度越快。如果需要长时间高速建索引,并且在建索引结束之前暂不执行查询,那么可以考虑将index.refresh_interval参数值设置为-1,然后在建索引结束以后再将该参数恢复为初始值。

3. 事务日志

Apache Lucene能保证索引的一致性,这非常棒,但是这并不能保证当往索引中写数据失败时不会损失数据(如磁盘空间不足、设备损坏,或没有足够的文件句柄供索引文件使用)。另外,频繁提交操作会导致严重的性能问题(因为每提交一次就会触发一个索引段的创建操作,同时也可能触发索引段的合并)。

ElasticSearch通过使用事务日志(transaction log)来解决上面的问题,它能保存所有的未提交的事务,而ElasticSearch会不时创建一个新的日志文件用于记录每个事务的后续操作。当有错误发生时,就会检查事务日志,必要时会再次执行某些操作,以确保没有丢失任何更改信息。而且,事务日志的相关操作都是自动完成的,用户并不会意识到某个特定时刻触发的更新提交。

事务日志中的信息与存储介质之间的同步(同时清空事务日志)称为事务日志刷新(flushing)
请注意事务日志刷新与Searcher刷新的区别。
- Searcher刷新:为了搜索到最新的文档
- 事务日志刷新:用来确保数据正确写入了索引并清空了事务日志。

事务日志的刷新行为是可以自定义的。以下参数既可以通过修改elasticsearch.yml文件来配置,也可以通过索引配置更新API来更改。

  • index.translog.flush_threshold_period:该参数的默认值为30分钟,它控制了强制自动事务日志刷新的时间间隔,即便是没有新数据写入。强制进行事务日志刷新通常会导致大量的I/O操作,因此当事务日志涉及少量数据时,才更适合进行这项操作。

  • index.translog.flush_threshold_ops:该参数确定了一个最大操作数,即在上次事务日志刷新以后,当索引更改操作次数超过该参数值时,强制进行事务日志刷新操作,默认值为5000。

  • index.translog.flush_threshold_size:该参数确定了事务日志的最大容量,当容量大于等于该参数值,就强制进行事务日志刷新操作,默认值为200MB。

  • index.translog.disable_flush:禁用事务日志刷新。尽管默认情况下事务日志刷新是可用的,但对它临时性地禁用能带来其他方面的便利。例如,向索引中导入大量文档的时候。在向索引导入大量数据时,禁止刷新可以大幅提高索引的速度。但是请记住,当数据导入完毕之后,要重新设置事务日志刷新相关参数。

3.1 准实时读取

实时读取操作从索引中读取数据时,会先检查事务日志中是否有可用的新版本。如果近期索引没有与事务日志同步,那么索引中的数据将会被忽略,事务日志中最新版本的文档将会被返回。

4. 控制索引合并

频繁的文档更改操作会导致大量的小索引段,索引段数量过多会带来如下问题:

  • 搜索性能越低
  • 耗费内存更多。
  • 删除操作,并没有物理上删除,只是做了标记删除操作
  • 文件句柄打开过多的问题。

段合并可以带来以下好处:
- 当多个索引段合并为一个的时候,会减少索引段的数量并提高搜索速度。
- 也会减少索引的容量(文档数),因为在段合并时会移除被标记为已删除的那些文档。

5. 合并的策略

  • tiered合并策略:这是ElasticSearch的默认选项。它能合并大小相似的索引段,并考虑每层允许的索引段的最大个数。在索引期,该合并策略会计算索引中允许出现的索引段个数,该数值称为阈值(budget)。如果正在构建的索引中的段数超过了阈值,该策略将先对索引段按容量降序排序(这里考虑了被标记为已删除的文档),然后再选择一个成本最低的合并。合并成本的计算方法倾向于回收更多删除文档和产生更小的索引段。

5.1 合并的调度

除了可以影响索引合并策略的行为之外,ElasticSearch还允许我们定制合并策略的执行方式。

  • 并发合并调度器(ConcurrentMergeScheduler):该调度器使用多线程执行索引合并操作,其具体过程是:每次开启一个新线程直到线程数达到上限,当达到线程数上限时,必须开启新线程(因为需要进行新的段合并),那么所有索引操作将被挂起,直到至少一个索引合并操作完成。
    为了控制最大线程数,可以通过修改index.merge.scheduler.max_thread_count属性来实现。一般来说,可以按如下公式来计算允许的最大线程数:
Math.max(1, Math.min(4, Runtime.getRuntime().availableProcessors() / 2))

6. I/O调节

段合并的计算量庞大, 而且还要吃掉大量磁盘 I/O。合并在后台定期操作,因为他们可能要很长时间才能完成,尤其是比较大的段。这个通常来说都没问题,因为大规模段合并的概率是很小的。

不过有时候合并会拖累写入速率。如果这个真的发生了,Elasticsearch 会自动限制索引请求到单个线程里。这个可以防止出现 段爆炸 问题,即数以百计的段在被合并之前就生成出来。如果 Elasticsearch 发现合并拖累索引了,它会会记录一个声明有 now throttling indexing 的 INFO 级别信息。

默认值是 20 MB/s,对机械磁盘应该是个不错的设置。如果你用的是 SSD,可以考虑提高到 100–200 MB/s。测试验证对你的系统哪个值合适:

PUT /_cluster/settings
{
    "persistent" : {
        "indices.store.throttle.max_bytes_per_sec" : "100mb"
    }
}

如果你在做批量导入,完全不在意搜索,你可以彻底关掉合并限流。这样让你的索引速度跑到你磁盘允许的极限:

PUT /_cluster/settings
{
    "transient" : {
        "indices.store.throttle.type" : "none" 
    }
}

Elasticsearch中可以配置节点级别或是索引级别的throttle,可以配置的类型包括none(不做限制),merge(限制merge),all(限制所有操作),配置的策略包括max_bytes_per_sec.

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值