本篇文章首要参考: 小册-Elasticsearch 从入门到实践

随着数据量的添加,MySQL在很多场景下,似乎已经无能为力了,所以有不少运用的数据从MySQL搬迁到了Elasticsearch,咱们的运用就在其间。由于开发时刻严峻,所以仅仅只是了解了下Elasticsearch的基本知识,随意写了几个Demo,然后直接在正式的环境中运用Elasticsearch。由于给咱们运用分配的Elasticsearch服务器满意强壮,Elasticsearch自身也规划的满意好,当时数据量也没有那么海量,并发也没有那么高,所以一直没有问题,可是该来的总会来,随着公司的发展,数据量也在直线添加,并发越来越高,功能问题越来越显着,看着公司内,有越来越多的运用接入了Elasticsearch,看着公司外,有越来越的公司也引入了Elasticsearch,我意识到有必要深化的了解下Elasticsearch。经过大半年的断断续续学习,终于对Elasticsearch有了一定的了解,可是我毕竟不是专门做查找引擎的,更没有强壮的算法、数据结构思维,所以对Elasticsearch的了解也仅仅是停留在“用的不这么差”的程度上,所以本篇博客首要是写给Java运用开发看的,假如是专门做查找引擎的,就一笑而过吧。

优化漏斗

但凡涉及到某个组件的功能调优,咱们在脑海中就要浮现出一张很经典的优化漏斗图:

写给Java应用开发看的Elasticsearch调优手册

左边便是很经典的漏斗图,漏斗分为四层,从上到下分别为:

  • 运用
  • 运用装备
  • JVM
  • OS

总的来说,层级在上面的,调优的作用越显着,由于咱们的Elasticsearch是独立布置在服务器上的,所以服务器的装备也至关重要。关于Elasticsearch而言,硬件装备是根底,正确的运用姿势是中心,缺一不可。

本篇博客,咱们就从这五个方面来对Elasticsearch进行调优。

硬件

Elasticsearch和一般运用不同,一般运用也许4C8G的装备就满意了,可是Elasticsearch需求比较好的装备,假如装备实在太低,就抛弃Elasticsearch吧。

节点装备

Elasticsearch有三个常用的节点类型:Master节点、数据节点、和谐节点,咱们来看下这三种节点的职责以及需求什么样的装备。

  • 数据节点:首要担任保存数据,查询数据,所以这个节点的装备要求是最高的,不管是CPU、内存、磁盘,都要高配的,磁盘最好选用RAID0、SSD,为什么是RAID0?由于Elasticsearch自身就有冗余副本的存在,能够确保不丢掉数据;
  • Master节点:一个Elasticsearch集群中只会有一个Master节点,Master首要担任办理集群变更、元数据的办理,该节点不需求太好的装备;
  • 和谐节点:接受客户端的恳求,并将恳求路由到数据节点,然后将数据节点回来的内容进行处理,比方合并,排序等等,所以此节点对CPU、内存的要求是比较高的。

为了愈加明晰,我给咱们准备了一个表格:

节点类型 CPU 内存 磁盘
数据节点 高装备 高装备 高装备
Master节点 低装备 低装备 低装备
和谐节点 高装备 高装备 低装备

咱们在做数据查询的时分,和谐节点会把恳求路由给多个数据节点,多个数据节点再把数据响应给和谐节点,和谐节点再对数据进行加工处理,回来给客户端,需求做多次数据转移,并且数据或许都不小,所以低推迟的网络也是必需的。

节点的单一职责

编码的时分,为了代码的扩展性、可维护性,咱们需求满意“单一职责”,在分配节点的时分,为了Elasticsearch的功能,也需求满意“单一职责”,即:一个节点只做一件工作。

想想也是,Master节点作为集群的老迈,相当于公司办理,数据节点是大头兵,假如Matser节点既要做办理的工作,又要做大头兵的工作,那会呈现什么局势?

所以在条件答应的状况下,一个节点只做一件工作。

分片数(每个分片的大小控制在30-50G,3-5个分片能够满意大部分场景)

每个分片的大小控制在30-50G,Elasticsearch是严峻依赖PageCache的,最好确保分片中的数据有1/3都在PageCache中。

假如你不想核算到底需求多少个分片,能够无脑装备3-5个分片,这满意大部分场景,毕竟一般的公司,你请求Elasticsearch集群,没有特别的阐明,运维小伙伴也是直接给你一个默许装备下的Elasticsearch集群,也不会特意问你数据的规模,假如你查询一下,会发现便是3-5个分片。

副本数(一个副本就够)

一个副本就够了,假如是数据搬迁,为了寻求搬迁的速度,乃至能够把副本封闭了,等数据搬迁完毕,再开启副本。

OS装备

禁用/少用swap

OS在内存不够用的时分,会将部分数据交换到swap空间(磁盘)上,可是磁盘的速度哪比得上内存的速度,所以会导致功能直线下降,所以应该封闭swap。

假如彻底禁用swap,当内存不够用,OS或许会kill进程,所以为了可用性,也有一些人以为不要彻底禁用swap,能够将swap设置成一个很小的数值,这样当功能直线下降,开发、运维都会有感知,能够给开发、运维处理的时刻。

文件描述符设置为65535或更大

封闭atime

每次读取文件,Linux都会更新atime,没有实际用途,能够封闭。

设置最少的线程数量

Elasticsearch运行时会创立多种线程池来执行各种各样的操作,所以有必要确保Elasticsearch能够创立满意的线程,而这个数量最少为4096。

减少TCP重传次数

Elasticsearch集群各个节点间的通信是运用TCP的,可是在丢包的状况下,Linux最多重传15次,而这15次重传会耗时900秒以上。这意味着体系发现网络分区故障需求十分长的时刻,所以能够恰当降低TCP重传次数。

JVM装备

最小堆内存和最大堆内存有必要一样

假如最小堆内存、最大堆内存不一样,在运行的过程中,会频频的进行伸缩。

最大堆内存不要超越服务器内存的一半

Elasticsearch是严峻依赖PageCache的,最好确保分片中的数据有1/3都在PageCache中,所以最大堆内存不要超越服务器内存的一半,剩下的给OS运用。

最大堆内存不要超越32G(为了保险,能够设置30G)

最大堆内存一旦超越32G,JVM就会禁用指针紧缩技能,这个时分,或许需求40-50G的内存才能够到达原先32G的作用,所以最大堆内存不要超越32G。32G是一个预算值,有些时分,或许不到32G就已经禁用了指针紧缩技能,所以为了保险,最大堆内存能够设置30G。

废物收集器选用G1

关于大内存来说,G1比CMS给力,所以能够选用G1废物收集器,还需求调整两个参数,假如G1整理失利了,会转为单线程废物收集,这就太恐怖了,而G1默许的InitiatingHeapOccupancyPercent设置太达观了,或许导致整理失利,所以需求恰当降低InitiatingHeapOccupancyPercent。

-XX:G1HeapRegionSize=16m
-XX:InitiatingHeapOccupancyPercent=30

运用装备

调整刷写频率

将文档写入Elasticsearch,会先写到buffer中,然后定时将buffer中的数据刷写到segment中,默许是1秒,能够恰当调高此装备,当然buffer写满了,也会刷写到segment,可是大部分场景下,都是满意了时刻的条件才触写刷新的。

装备项如下:

index.refresh_interval //默许是1秒,能够恰当调高此装备
indices.memory.index_buffer_size //既能够装备字节数,又能够装备份额,这个参数是节点内一切分片共享的

写translog改为异步方式

translog是用来确保数据不丢掉的,类似于MySQL的binlog,默许写translog是同步的,能够改为异步的方式。

装备项如下:

index.translog.durability: async //默许是request
index.translog.sync_interval: 60s

运用

尽或许运用体系主动生成的Id

假如不运用体系主动生成的Id,Elasticsearch会查看给定的Id是否重复,从而产生IO,假如能够的话,尽或许运用体系主动生成的Id。

批量写入

经验值是一次性写入5000到10000条数据。

曾经我一直觉得批量写入简直只要在数据搬迁的时分才或许实现,平时简直都是单条写入的,其实假如事务答应,能够先将恳求用MQ中转下,Consumer消费MQ数据,将数据放入堵塞行列,别的一个线程用Google Guava提供的方法批量从堵塞行列中获取数据,终究批量写入Elasticsearch。

示例代码如下:

当然这样就添加代码的杂乱度了,还要处理各种的异常场景,我这儿仅仅是忽然想到一个方法,和咱们分享下。

mapping

字段越少越好,合适的数据类型

运用Keyword类型

关于等值查询而言,keyword比数值类型功能更好,所以假如不需求规模查询,能够运用Keyword类型。 不需求分词的文本,最好运用keyword,否则既影响写入功能,又占用空间。

假如不需求被索引,设置index为no

有不需求进行查找的字段,能够设置其不需求索引,否则既影响写入功能,又占用空间。

假如不需求聚合、排序,设置doc_values为false

Docvalues是基于列式存储的结构,聚合、排序十分高效,默许开启,占用空间。

扁平化(尽或许防止nested、parent-child)

尽或许防止nested、parent-child,否则既影响写入功能,又影响查询功能。

假如一个字段不需求算分,能够封闭Norms

假如当前字段不需求核算评分,设置false能够节约很多的磁盘空间,有助于提升功能。

不要运用Dynamic Mapping

假如运用Dynamic Mapping,那默许状况下,一切字段都是需求被索引的,并且都会创立doc_values,这必定不是咱们期望的,所以不要运用Dynamic Mapping,要自己严格界说mapping。

不要对text类型的字段进行排序

预索引

产品价格区间的查找,比方能够查看价格100-200的产品,200-500的产品,500-1000的产品,那索引中必定含有price字段,咱们能够经过规模查询查找出对应的产品,可是规模查询的功能必定没有等值查询好,那咱们能够在索引中再加一个字段:price_type(当price为100-200,price_type=1,当price为200-500,price_type=2,以此类推),这样咱们就能够运用等值查询了。

查询某个月的数据,那索引中必定含有time字段,咱们能够经过规模查询查找出对应的数据,假如咱们加一个month字段(yyyyMM),就能够选用等值查询了。

运用索引模板,对数据进行分片

相当于MySQL的分库分表,可是愈加便利,只要界说一个模板,推送的数据满意相应的条件,就能够主动将索引创立出来。

防止深度分页,运用scroll和search_after分页

HBase和Elasticsearch搭配更香

Elasticsearch严峻依赖PageCache,最好不要把太多字段放入Elasticsearch,会占用很多PageCache,查询会走到硬盘,严峻影响查询功能,能够把中心字段、条件字段放Elasticsearch,其他数据放到HBase,经过_id去HBase查询更为明细的数据,假如HBase不可用,再查询MySQL,进步可用性。

运用Routing

默许状况: 刺进数据是依据_id进行路由,挑选某个分片:

  • 长处:运用简略,每个分片的数据量比较均匀;
  • 缺陷:查询会扫描一切分片,开销比较大,功能取决于最慢的分片。

运用routing: 刺进数据是依据给定的routing进行路由,写入到某个分片,查询的时分,也能够指定查询某个分片。

  • 长处:功能更好;
  • 缺陷:运用比较杂乱,需求自己控制写入的分片和查询的分片。

以上便是常用的Elasticsearch调优技巧,当然Elasticsearch的调优技巧远不止这些,比方比较高端的_sourse、store设置等等。

咱们有没有发现,其间很多调优技巧,都是通用的,比方合适的数据类型,字段越少越好,预索引,比方添加文件描述符数量、封闭atime等等。

本文正在参与「金石计划 . 瓜分6万现金大奖」