<漫谈ElasticSearch>关于ES性能调优几件必须知道的事

原创博客,转载请联系博主!html

 

 

 

(零)ElasticSearch架构概述java

 

ElasticSearch是如今技术前沿的大数据引擎,常见的组合有ES+Logstash+Kibana做为一套成熟的日志系统,其中Logstash是ETL工具,Kibana是数据分析展现平台。ES让人惊艳的是他强大的搜索相关能力和灾备策略,ES开放了一些接口供开发者研发本身的插件,ES结合中文分词的插件会给ES的搜索和分析起到很大的推进做用。ElasticSearch是使用开源全文检索库ApacheLucene进行索引和搜索的,说架构必须和Lucene的一些东西打交道。数据库

 

关于Lucene:bootstrap

ApacheLucene将写入索引的全部信息组织成一种倒排索引(Inverted Index)的结构之中,该结构是种将词项映射到文档的数据结构。其工做方式与传统的关系数据库不一样,大体来讲倒排索引是面向词项而不是面向文档的。且Lucene索引之中还存储了不少其余的信息,如词向量等等,每一个Lucene都是由多个构成的,每一个段只会被建立一次但会被查询屡次,段一旦建立就不会再被修改。多个段会在段合并的阶段合并在一块儿,什么时候合并由Lucene的内在机制决定,段合并后数量会变少,可是相应的段自己会变大。段合并的过程是很是消耗I/O的,且与之同时会有些再也不使用的信息被清理掉。在Lucene中,将数据转化为倒排索引,将完整串转化为可用于搜索的词项的过程叫作分析。文本分析由分析器(Analyzer)来执行,分析其由分词器(Tokenizer),过滤器(Filter)和字符映射器(Character Mapper)组成,其各个功能显而易见。除此以外,Lucene有本身的一套完整的查询语言来帮助咱们进行搜索和读写。网络

 

 [注]ES中的索引指的是查询/寻址时URI中的一个字段如:[host]:[port(9200)]/[index]/[type]/[ID]?[option],而Lucene中的索引更多地和ES中的分片的概念相对应。数据结构

 

回到ElasticSearch,ES的架构遵循的设计理念有如下几个特征:架构

 

1. 合理的默认配置:只需修改节点中的Yaml配置文件,就能够迅捷配置。这和Spring4中对配置的简化有类似的地方。oracle

2. 分布式工做模式:ES强大的Zen发现机制不只支持组广播也支持点单播,且有“知一点即知天下”之妙。app

3. 对等架构:节点之间自动备份分片,且使分片自己和样本之间尽可能”远离“,能够避免单点故障。且Master节点和Data节点几乎彻底等价。运维

4. 易于向集群扩充新节点:大大简化研发或运维将新节点加入集群所需的工做。

5. 不对索引中的数据结构增长任何限制:ES支持在一个索引之中存在多种数据类型。

6. 准实时:搜索和版本同步,因为ES是分布式应用,一个重大的挑战就是一致性问题,不管索引仍是文档数据,然而事实证实ES表现优秀。

 

 

(一)分片策略

 

选择合适的分片数和副本数ES的分片分为两种,主分片(Primary Shard)和副本(Replicas)。默认状况下,ES会为每一个索引建立5个分片,即便是在单机环境下,这种冗余被称做过分分配(Over Allocation),目前看来这么作彻底没有必要,仅在散布文档到分片和处理查询的过程当中就增长了更多的复杂性,好在ES的优秀性能掩盖了这一点。假设一个索引由一个分片构成,那么当索引的大小超过单个节点的容量的时候,ES不能将索引分割成多份,所以必须在建立索引的时候就指定好须要的分片数量。此时咱们所能作的就是建立一个新的索引,并在初始设定之中指定这个索引拥有更多的分片。反之若是过分分配,就增大了Lucene在合并分片查询结果时的复杂度,从而增大了耗时,因此咱们获得了如下结论:

咱们应该使用最少的分片!

主分片,副本和节点最大数之间数量存在如下关系:

节点数<=主分片数*(副本数+1)

 

 控制分片分配行为。以上是在建立每一个索引的时候须要考虑的优化方法,然而在索引已建立好的前提下,是否就是没有办法从分片的角度提升了性能了呢?固然不是,首先能作的是调整分片分配器的类型,具体是在elasticsearch.yml中设置cluster.routing.allocation.type属性,共有两种分片器even_shard,balanced(默认)。even_shard是尽可能保证每一个节点都具备相同数量的分片,balanced是基于可控制的权重进行分配,相对于前一个分配器,它更暴漏了一些参数而引入调整分配过程的能力。

每次ES的分片调整都是在ES上的数据分布发生了变化的时候进行的,最有表明性的就是有新的数据节点加入了集群的时候。固然调整分片的时机并非由某个阈值触发的,ES内置十一个裁决者来决定是否触发分片调整,这里暂不赘述。另外,这些分配部署策略都是能够在运行时更新的,更多配置分片的属性也请你们自行Google。

 

 

(二)路由优化

 

ES中所谓的路由和IP网络不一样,是一个相似于Tag的东西。在建立文档的时候,能够经过字段为文档增长一个路由属性的Tag。ES内在机制决定了拥有相同路由属性的文档,必定会被分配到同一个分片上,不管是主分片仍是副本。那么,在查询的过程当中,一旦指定了感兴趣的路由属性,ES就能够直接到相应的分片所在的机器上进行搜索,而避免了复杂的分布式协同的一些工做,从而提高了ES的性能。于此同时,假设机器1上存有路由属性A的文档,机器2上存有路由属性为B的文档,那么我在查询的时候一旦指定目标路由属性为A,即便机器2故障瘫痪,对机器1构不成很大影响,因此这么作对灾况下的查询也提出了解决方案。所谓的路由,本质上是一个分桶(Bucketing)操做。固然,查询中也能够指定多个路由属性,机制大同小异。

 

 

(三)ES上的GC调优

 

ElasticSearch本质上是个Java程序,因此配置JVM垃圾回收器自己也是一个颇有意义的工做。咱们使用JVM的Xms和Xmx参数来提供指定内存大小,本质上提供的是JVM的堆空间大小,当JVM的堆空间不足的时候就会触发致命的OutOfMemoryException。这意味着要么内存不足,要么出现了内存泄露。处理GC问题,首先要肯定问题的源头,通常有两种方案:

 

1. 开启ElasticSearch上的GC日志

2. 使用jstat命令

3. 生成内存Dump

 

关于第一条,在ES的配置文件elasticsearch.yml中有相关的属性能够配置,关于每一个属性的用途这里固然说不完。

第二条,jstat命令能够帮助咱们查看JVM堆中各个区的使用状况和GC的耗时状况。

第三条,最后的办法就是将JVM的堆空间转储到文件中去,实质上是对JVM堆空间的一个快照。

想了解更多关于JVM自己GC调优方法请参考:http://www.oracle.com/technetwork/java/javase/gc-tuning-6-140523.html

另外,经过修改ES节点的启动参数,也能够调整GC的方式,可是实质上和上述方法是等同的。

 

 

(四)避免内存交换

 

这一点很简单,因为操做系统的虚拟内存页交换机制,会给性能带来障碍,如数据写满内存会写入Linux中的Swap分区。

能够经过在elasticsearch.yml文件中的bootstrap.mlockall设置为true来实现,可是须要管理员权限,须要修改操做系统的相关配置文件。

 

 

(五)控制索引合并

 

上文提到过,ES中的分片和副本本质上都是Lucene索引,而Lucene索引又基于多个索引段构建(至少一个),索引文件中的绝大多数都是只被写一次,读屡次,在Lucene内在机制控制下,当知足某种条件的时候多个索引段会被合并到一个更大的索引段,而那些旧的索引段会被抛弃并移除磁盘,这个操做叫作段合并。 

Lucene要执行段合并的理由很简单充分:索引段粒度越小,查询性能越低且耗费的内存越多。频繁的文档更改操做会致使大量的小索引段,从而致使文件句柄打开过多的问题,如修改系统配置,增大系统容许的最大文件打开数。总的来说,当索引段由多一个合并为一个的时候,会减小索引段的数量从而提升ES性能。对于研发者来说,咱们所能作的就是选择合适的合并策略,尽管段合并彻底是Lucene的任务,但随着Lucene开放更多配置借口,新版本的ES仍是提供了三种合并的策略tiered,log_byte_size,log_doc。另外,ES也提供了两种Lucene索引段合并的调度器:concurrent和serial。其中各者具体区别,这里暂不赘述,只是抛砖引玉。

 

 

 

打字好累,你们晚安。

相关文章
相关标签/搜索