硬件优化

Elasticsearch的基础是Lucene,所有的素引和文档数据是存储在本地的磁盘中,具体的路径可在ES的配置文件./config/elasticsearch.yml中配置,如下:
ELasticSearch优化_缓存系统
磁盘在现代服务器上通常都是瓶颈。Elasticsearch 重度使用磁盘,你的磁盘能处理的吞吐量越大,你的节点就越稳定。这里有一些优化磁盘I/O的技巧:

  • 使用RAID 0。条带化RAID会提高磁盘I/O,代价显然就是当一块硬盡故障时整个就故障了。不要使用镜像或者奇偶校验RAID因为副本已经提供了这个功能。
  • ·使用SSD.就像其他地方提过的, 他们比机械磁盘优秀多了。
  • 另外,使用多块硬盘,并允许Elatiseach通过多个path. data 目录配置把数据条带化分配到它们上面。
  • 不要使用远程挂载的存储,比如NFS或者SMB/CIFS.这个引入的延迟对性能来说完全是背道而驰的。

分片策略

分片和副本的设计为ES提供了支持分布式和故障转移的特性,但并不意味着分片和副本是可以无限分配的。而且索引的分片完成分配后由于索引的路由机制,我们是不能重新修改分片数的。 (一旦分片设定完成后,后续数不能更改的,副本可以修改,因为这里涉及到路由的计算规则,也就是数据存放在哪个分片上,一旦分片数量发生变化了,那么查询数据就查不到了,所以分片一定是在创建索引是就确定好的)可能有人会说,我不知道这个索引将来会变得多大,并且过后我也不能更改索引的大小,·所以为了保险起见,还是给它设为1000个分片吧。但是需要知道的是,一个分片并不是没有代价的。需要了解:

  • 一个分片的底层即为一个Lucene索引,会消耗一定文件句柄、内存、以及CPU运转。
  • ,每一个搜索请求都需要命中索引中的每一个分片,如果每一个分片都处于不同的节点还好, 但如果多个分片都需要在同一个节惠上竞争使用相同的资源就有些槽糕了。
  • 用于计算相关度的词项统计信息是基于分片的。如果有许多分片,每一个都只有很少的数据会导致很低的相关度。

一个业务索引具体需要分配多少分片可能需要架构师和技术人员对业务的增长有个预先的判断,横向扩展应当分阶段进行。为下一阶段准备好足够的资源。只有当你进入到下一个阶段,你才有时间思考需要作出哪些改变来达到这个阶段。一般来说,我们遵循一些原则:如下

  1. 控制每个分片占用的硬盘容量不超过ES的最大JVM的堆空间设置(一般设置不超过32G,参考下文的JVM设置原则) ,因此,如果索引的总容量在500G左右,那分片大小在16个左右即可;当然最好同时考虑
  2. 考虑一下node数量,1一般一个节点有时候就是一台物理机,如果分片数过多,大大超过了节点数.很可能会导致一个节点上存在多个分片,一旦该节点故障,即使保持了1个以上的副本,同样有可能会导致数据丢失,集群无法恢复。所以, 一般都设置分片数不超过节点数的3倍。
  3. 主分片,副本和节点最大数之间数量,我们分配的时候可以参考以下关系:节点数<主分片数* (副本数+1)

推迟分片分配

对于节点瞬时中断的问题,默认情况,集群会等待一分钟来查看节点是否会重新加入,如果这个节点在此期间重新加入,重新加入的节点会保持其现有的分片数据,不会触发新的· 分片分配。这样就可以减少ES在自动再平衡可用分片时所带来的极大开销。通过修改参数delayed timeout ,可以延长再均衡的时间,可以全局设置也可以在索引级别进行修改:

PUT /_all/_settings
{
	"settings":{
		"index.unassigned.node left.delayed_timeout": "5m"
	}
}

路由选择

当我们查询文档的时候, Elasticsearch如何知道一个文档应该存放到哪个分片中呢?它其实是通过下面这个公式来计算出来:
shard= hash(routing) % number_of_primary_shards
routing默认值是文档的id,也可以采用自定义值,比如用户id.

不带路由(routing)查询
在查询的时候因为不知道要查询的数据具体在哪个分片上,所以整个过程分为2个步骤

  • 分发:请求到达协调节点后,协调节点将查询请求分发到每个分片上。
  • 聚合:协调节点搜集到每个分片上查询结果,在将查询的结果进行排序,之后给用户返回结果。

带路由(routing)查询
查询的时候,可以直接根据routing信息定位到某个分配查询,不需要查询所有的分片经过协调节点排序。向上面自定义的用户查询,如果routing设置为userid的话,就可以直接查询出数据来,效率提升很多。

写入速度优化

ES的默认配置,是综合了数据可靠性、写入速度、搜索实时性等因素。实际使用时,我们需要根据公司要求,进行偏向性的优化。针对于搜索性能要求不高,但是对写入要求较高的场景,我们需要尽可能的选择恰当写优化策略。综合来说,可以考虑以下几个方面来提升写索引的性能:

  • 加大Translog Flush ,目的是降低lops、 Writeblock
  • 增加Index Refresh间隔, 目的是减少Segment Merge的次数。
  • 调整Bulk线程池和队列。
  • 优化节间的任务分布。
  • 优化Lucene层的索引建立, 目的是降低CPU及I/O

批量数据提交
优化Lucene层的索引建立, 目的是降低CPU及I/O,通用的策略如下: Bulk默认设置批量提交的数据量不能超过100M。数据条数一般是根据文档的大小和服务器性能而定的,但是单次批处理的数据大小应从5MB~15MB逐渐增加,当性能没有提升时,把这个数据量作为最大值。

优化存储设备
ES是一种密集使用磁盘的应用,在段合并的时候会频繁操作磁盘,所以对磁盘要求较ES是一种密集使用磁盘的应用,在段合并的时候会频繁操作磁盘,所以对磁盘要求较

合理使用合并
Lucene以段的形式存储数据。当有新的数据写入索引时, Lucene就会自动创建一个新的段。随着数据量的变化,段的数量会越来越多,消耗的多文件句柄数及CPU就越多,查询效率就会下降。由于Lucene段合并的计算量庞大,会消耗大量的1O,所以ES默认采用较保守的策略,让后台定期进行段合并

减少Refresh次数
Lucene在新增数据时,采用了延迟写入的策略,默认情况下索引的refresh interval为1秒。 Lucene将待写入的数据先写到内存中,超过1秒(默)时就会触发一次Refiesh,然后Refiesh会把内存中的的数据刷新到操作系统的戈件缓存系统中。Lucene将待写入的数据先写到内存中,超过1秒(默)时就会触发一次Refiesh,然后Refiesh会把内存中的的数据刷新到操作系统的戈件缓存系统中。,这样还可以有效地减少段刷新次数,但这同时意味着需要消耗更多的Heap内存。

加大Flush设置
Flush的主要目的是把文件缓存系统中的段持久化到硬盘, 当Translog的数据量达到512MB或者30分钟时,会触发一次Flush,index.translog.flush_threshold_size参数的默认值是512MB,我们进行修改。增加参数值意味者文件缓存系统中可能需要存储更多的数据,所以我们需要为操作系统的文件缓存系统留下足够的空间。

减少副本数量
ES为了保证集群的可用性,提供了Replicas (副本)支持,然而每个副本也会执行分断、索引及可能的合并过程,所以Replicas的数量会严重影响写索引的效率。当写索引时,需要把写入的数据都同步到副本节点,副本节点越多,写索引的效率就越慢。 ES为了保证集群的可用性,提供了Replicas (副本)支持,然而每个副本也会执行分断、索引及可能的合并过程,所以Replicas的数量会严重影响写索引的效率。当写索引时,需要把写入的数据都同步到副本节点,副本节点越多,写索引的效率就越慢。

内存设置

ES默认安装后设置的内存是1GB,对于任何一个现实业务来说,这个设置都太小了。如果是通过解压安装的ES,则在ES安装文件中包含一个jvm.option文件,添加如下命令来设置ES的堆大小,Xms表示堆的初始大小,Xmx表示可分配的最大内存,都是1GB.确保Xmx和Xms的大小是相同的,其目的是为了能够在Java垃圾回收机制清理完堆区后不需要重新分隔计算堆区的大小而浪费资源,可以减轻伸缩堆大小带来的压力。假设你有一个64G内存的机器,按照正常思维思考,你可能会认为把64G内存都给ES比较好,但现实是这样吗, 越大越好?虽然内存对ES来说是非常重要的,但是答案是否定的!,因为ES堆内存的分配需要满足以下两个原则:

  • 不要超过物理内存的50%,Lncene的设计目的是把底层OS里的数据缓存到内存中。Lucene的段是分别存储到单个文件中的,这些文件都是不会变化的,所以很利于缓存,同时操作系统也会把这些段文件缓存起来,以便更快的访问。如果我们设置的堆内存过大, Lucene可用的内存将会减少,就会严重影响降低Lucene的全文本查询性能。
  • 堆内存的大小最好不要超过32GB;在Java中,所有对象都分配在堆上,然后有一个Klass Pointer指针指向它的类元数据。这个指针在64位的操作系统上为64位, 64位的操作系统可以使用更多的内存(2^64)。在32位的系统上为32位, 32位的操作系统的最大寻址空间为4GB (2^32)但是64位的指针意味着更大的浪费,因为你的指针本身大了。浪费内存不算,更糟糕的是,更大的指针在主内存和缓存器(例如LLC. L1等)之间移动数据的时候,会占用更多的带宽。最终我们都会采用31G设置
-Xms 31g
-Xmx 31g

假设你有个机器有128 GB的内存,你可以创建两个节点,每个节点内存分配不超过32GB,也就是说不超过64GB内存给ES的堆内存,剩下的超过64GB的内存给Lucene