ElasticSearch 功能调优

ElasticSearch还能性能调优,涨见识、涨见识了!!!

  • 作者: 博学谷狂野架构

  • GitHub地址:GitHub地址 (有咱们精心预备的130本电子书PDF)

概述

功能优化是个涉及面十分广的问题,不同的环境,不同的事务场景或许会存在不同的优化计划,本文只对一些相关的知识点做简略的总结,详细计划能够依据场景自行尝试。

装备文件调优

经过elasticsearch.yml装备文件调优

内存确认

答应 JVM 锁住内存,制止操作体系交流出去

由于JVM产生swap交流会导致极大下降ES的功能,为了防止ES产生内存交流,咱们能够经过确认内存来实现,这将极大进步查询功能,但一起或许构成OOM,需求对应做好资源监控,必要的时分进行干预。

修正ES装备

修正ES的装备文件elasticsearch.yml,设置bootstrap.memory_lock为true

COPY#集群称号
cluster.name: elastic
#当时该节点的称号
node.name: node-3
#是不是有资历竞选主节点
node.master: true
#是否存储数据
node.data: true
#最大集群节点数
node.max_local_storage_nodes: 3
#给当时节点自定义特点(能够省略)
#node.attr.rack: r1
#数据存档方位
path.data: /usr/share/elasticsearch/data
#日志存放方位
path.logs: /usr/share/elasticsearch/log
#是否敞开时确认内存(默以为是)
#bootstrap.memory_lock: true
#设置网关地址,我是被这个坑死了,这个地址我原先填写了自己的实践物理IP地址,
#然后发动一向报无效的IP地址,无法注入9300端口,这儿只需求填写0.0.0.0
network.host: 0.0.0.0
#设置映射端口
http.port: 9200
#内部节点之间沟通端口
transport.tcp.port: 9300
#集群发现默许值为127.0.0.1:9300,假如要在其他主机上构成包括节点的群集,假如树立集群则需求填写
#es7.x 之后新增的装备,写入候选主节点的设备地址,在敞开服务后能够被选为主节点,也便是说把一切的节点都写上
discovery.seed_hosts: ["node-1","node-2","node-3"]
#当你在树立集群的时分,选出合格的节点集群,有些人说的太官方了,
#其实便是,让你挑选比较好的几个节点,在你节点发动时,在这些节点中选一个做领导者,
#假如你不设置呢,elasticsearch就会自己推举,这儿咱们把三个节点都写上
cluster.initial_master_nodes: ["node-1","node-2","node-3"]
#在群集彻底从头发动后阻止初始康复,直到发动N个节点
#简略点说在集群发动后,至少复活多少个节点以上,那么这个服务才能够被运用,不然不能够被运用,
gateway.recover_after_nodes: 2
#删去索引是是否需求显现其称号,默以为显现
#action.destructive_requires_name: true
# 答应内存确认,进步ES功能
bootstrap.memory_lock: true
修正JVM装备

修正jvm.options,通常设置-Xms和-Xmx的的值为“物理内存巨细的一半和32G的较小值”

这是由于,es内核运用lucene,lucene自身是独自占用内存的,并且占用的还不少,官方主张设置es内存,巨细为物理内存的一半,剩下的一半留给lucene

COPY-Xms2g
-Xmx2g
封闭操作体系的swap
临时封闭
COPYsudo swapoff -a
永久封闭

注释掉或删去一切swap相关的内容

COPYvi /etc/fstab

ElasticSearch还能性能调优,涨见识、涨见识了!!!

修正文件描绘符

修正/etc/security/limits.conf,设置memlock为unlimited

COPYelk hard memlock unlimited
elk soft memlock unlimited
修正体系装备
设置虚拟内存

修正/etc/systemd/system.conf,设置vm.max_map_count为一个较大的值

COPYvm.max_map_count=10240000
修正文件上限

修正/etc/systemd/system.conf,设置DefaultLimitNOFILE,DefaultLimitNPROC,DefaultLimitMEMLOCK为一个较大值,或许不限定

COPYDefaultLimitNOFILE=100000
DefaultLimitNPROC=100000
DefaultLimitMEMLOCK=infinity
重启ES

服务发现优化

Elasticsearch 默许被装备为运用单播发现,以防止节点无意中参加集群

组播发现应该永久不被运用在出产环境了,不然你得到的成果便是一个节点意外的参加到了你的出产环境,仅仅是由于他们收到了一个过错的组播信号,ES是一个P2P类型的分布式体系,运用gossip协议,集群的恣意恳求都能够发送到集群的任一节点,然后es内部会找到需求转发的节点,并且与之进行通信,在es1.x的版别,es默许是敞开组播,发动es之后,能够快速将局域网内集群称号,默许端口的相同实例参加到一个大的集群,后续再es2.x之后,都调整成了单播,防止安全问题和网络风暴;

单播discovery.zen.ping.unicast.hosts,主张写入集群内一切的节点及端口,假如新实例参加集群,新实例只需求写入当时集群的实例,即可主动参加到当时集群,之后再处理原实例的装备即可,新实例参加集群,不需求重启原有实例;

节点zen相关装备:discovery.zen.ping_timeout:判别master推举过程中,发现其他node存活的超时设置,首要影响推举的耗时,参数仅在参加或许推举 master 主节点的时分才起作用discovery.zen.join_timeout:节点确认参加到集群中,向主节点发送参加恳求的超时时刻,默以为3sdiscovery.zen.minimum_master_nodes:参加master推举的最小节点数,当集群能够被选为master的节点数量小于最小数量时,集群将无法正常推举。

毛病检测( fault detection )

毛病检测状况

以下两种状况下回进行毛病检测

COPY* 第一种是由master向集群的一切其他节点主张ping,验证节点是否处于活动状态
* 第二种是:集群每个节点向master主张ping,判别master是否存活,是否需求主张推举
装备方法

毛病检测需求装备以下设置运用

  • discovery.zen.fd.ping_interval :节点被ping的频率,默以为1s。
  • discovery.zen.fd.ping_timeout 等待ping呼应的时刻,默以为 30s,运转的集群中,master 检测一切节点,以及节点检测 master 是否正常。
  • discovery.zen.fd.ping_retries ping失败/超时多少导致节点被视为失败,默以为3。

行列数量优化

不主张盲目加大es的行列数量,要依据实践状况来进行调整

假如是偶发的由于数据突增,导致行列阻塞,加大行列size能够运用内存来缓存数据,假如是持续性的数据阻塞在行列,加大行列size除了加大内存占用,并不能有用进步数据写入速率,反而或许加大es宕机时分,在内存中或许丢失的上数据量。

检查线程池状况

经过以下能够检查线程池的状况,哪些状况下,加大行列size呢?

COPYGET /_cat/thread_pool

ElasticSearch还能性能调优,涨见识、涨见识了!!!

观察api中回来的queue和rejected,假如确实存在行列回绝或许是持续的queue,能够酌情调整行列size。

内存运用

装备熔断限额

设置indices的内存熔断相关参数,依据实践状况进行调整,防止写入或查询压力过高导致OOM

  • indices.breaker.total.limit: 50%,集群等级的断路器,默以为jvm堆的70%
  • indices.breaker.request.limit: 10%,单个request的断路器约束,默以为jvm堆的60%
  • indices.breaker.fielddata.limit: 10%,fielddata breaker约束,默以为jvm堆的60%。
装备缓存

依据实践状况调整查询占用cache,防止查询cache占用过多的jvm内存,参数为静态的,需求在每个数据节点装备

  • indices.queries.cache.size: 5%,操控过滤器缓存的内存巨细,默以为10%,接受百分比值,5%或许准确值,例如512mb。

创立分片优化

假如集群规模较大,能够阻止新建shard时扫描集群内全部shard的元数据,进步shard分配速度

  • cluster.routing.allocation.disk.include_relocations: false,默以为true

体系层面调优

jdk版别

选用当时版别ES推荐运用的ES,或许运用ES自带的JDK

jdk内存装备

首要,-Xms和-Xmx设置为相同的值,防止在运转过程中再进行内存分配,一起,假如体系内存小于64G,主张设置略小于机器内存的一半,剩余留给体系运用,一起,jvm heap主张不要超越32G(不同jdk版别详细的值会略有不同),不然jvm会由于内存指针紧缩导致内存浪费

封闭交流分区

封闭交流分区,防止内存产生交流导致功能下降(部分状况下,宁死勿慢) swapoff -a

文件句柄

Lucene 运用了 许多的 文件,一起,Elasticsearch 在节点和 HTTP 客户端之间进行通信也运用了许多的套接字,一切这一切都需求足够的文件描绘符,默许状况下,linux默许运转单个进程打开1024个文件句柄,这明显是不够的,故需求加大文件句柄数 ulimit -n 65536

mmap

Elasticsearch 对各种文件混合运用了 NioFs( 注:非阻塞文件体系)和 MMapFs ( 注:内存映射文件体系)。

请确保你装备的最大映射数量,以便有足够的虚拟内存可用于 mmapped 文件。这能够暂时设置:sysctl -w vm.max_map_count=262144 或许你能够在 /etc/sysctl.conf 经过修正 vm.max_map_count 永久设置它。

磁盘

假如你正在运用 SSDs,确保你的体系 I/O 调度程序是装备正确的

当你向硬盘写数据,I/O 调度程序决议何时把数据实践发送到硬盘,大多数默许linux 发行版下的调度程序都叫做 cfq(彻底公平行列),但它是为旋转介质优化的:机械硬盘的固有特性意味着它写入数据到依据物理布局的硬盘会更高效。

这对 SSD 来说是低效的,尽管这儿没有涉及到机械硬盘,可是,deadline 或许 noop 应该被运用,deadline 调度程序依据写入等待时刻进行优化, noop 仅仅一个简略的 FIFO 行列。

COPYecho noop > /sys/block/sd/queue/scheduler

磁盘挂载

COPYmount -o noatime,data=writeback,barrier=0,nobh /dev/sd* /esdata*

其间,noatime,制止记载访问时刻戳;data=writeback,不记载journal;barrier=0,由于封闭了journal,所以同步封闭barrier;nobh,封闭buffer_head,防止内核影响数据IO

磁盘其他注意事项

运用 RAID 0,条带化 RAID 会进步磁盘I/O,代价明显便是当一块硬盘毛病时整个就毛病了,不要运用镜像或许奇偶校验 RAID 由于副本已经供给了这个功能。

别的,运用多块硬盘,并答应 Elasticsearch 经过多个 path.data 目录装备把数据条带化分配到它们上面,不要运用远程挂载的存储,比方 NFS 或许 SMB/CIFS。这个引入的延迟对功能来说彻底是背道而驰的。

运用方法调优

当elasticsearch自身的装备没有明显的问题之后,发现es运用仍是十分慢,这个时分,就需求咱们去定位es自身的问题了,首要祭出定位问题的第一个指令:

Index(写)调优

副本数置0

假如是集群初次灌入数据,能够将副本数设置为0,写入完毕再调整回去,这样副本分片只需求拷贝,节省了索引过程

COPYPUT /my_temp_index/_settings
{
"number_of_replicas": 0
}
主动生成doc ID

经过Elasticsearch写入流程能够看出,假如写入doc时假如外部指定了id,则Elasticsearch会先尝试读取本来doc的版别号,以判别是否需求更新,这会涉及一次读取磁盘的操作,经过主动生成doc ID能够防止这个环节

合理设置mappings

将不需求树立索引的字段index特点设置为not_analyzed或no。

  • 对字段不分词,或许不索引,能够削减许多运算操作,下降CPU占用,尤其是binary类型,默许状况下占用CPU十分高,而这种类型进行分词通常没有什么意义。
  • 削减字段内容长度,假如原始数据的大段内容无须全部树立 索引,则能够尽量削减不必要的内容。
  • 运用不同的剖析器(analyzer),不同的剖析器在索引过程中 运算复杂度也有较大的差异。
调整_source字段
_source` 字段用于存储 doc 原始数据,关于部分不需求存储的字段,能够经过 includes excludes过滤,或许将`_source`禁用,一般用于索引和数据别离,这样能够下降 I/O 的压力,不过实践场景中大多不会禁用`_source
对analyzed的字段禁用norms

Norms用于在查找时计算doc的评分,假如不需求评分,则能够将其禁用

COPYtitle": {
"type": "string",
"norms": {
"enabled": false
}
调整索引的改写距离

该参数缺省是1s,强制ES每秒创立一个新segment,然后确保新写入的数据近实时的可见、可被查找到,比方该参数被调整为30s,下降了改写的次数,把改写操作耗费的体系资源释放出来给index操作运用

COPYPUT /my_index/_settings
{
 "index" : {
      "refresh_interval": "30s"
    }
}

这种计划以牺牲可见性的方法,进步了index操作的功能。

批处理

批处理把多个index操作恳求兼并到一个batch中去处理,和mysql的jdbc的bacth有相似之处

ElasticSearch还能性能调优,涨见识、涨见识了!!!

比方每批1000个documents是一个功能比较好的size,每批中多少document条数适宜,受许多要素影响而不同,如单个document的巨细等,ES官网主张经过在单个node、单个shard做功能基准测验来确认这个参数的最优值

Document的路由处理

当对一批中的documents进行index操作时,该批index操作所需的线程的个数由要写入的意图shard的个数决议

ElasticSearch还能性能调优,涨见识、涨见识了!!!

有2批documents写入ES, 每批都需求写入4个shard,所以总共需求8个线程,假如能削减shard的个数,那么耗费的线程个数也会削减,例如下图,两批中每批的shard个数都只要2个,总共线程耗费个数4个,削减一半。

默许的routing便是id,也能够在发送恳求的时分,手动指定一个routing value,比方说put/index/doc/id?routing=user_id

ElasticSearch还能性能调优,涨见识、涨见识了!!!

值得注意的是线程数尽管下降了,可是单批的处理耗时或许增加了。和进步改写距离方法相似,这有或许会延伸数据不见的时刻

Search(读)调优

在存储的Document条数超越10亿条后,咱们怎么进行查找调优

数据分组

许多人拿ES用来存储日志,日志的索引办理方法一般依据日期的,依据天、周、月、年建索引,如下图,依据天建索引

ElasticSearch还能性能调优,涨见识、涨见识了!!!

当查找单天的数据,只需求查询一个索引的shards就能够,当需求查询多天的数据时,需求查询多个索引的shards,这种计划其实和数据库的分表、分库、分区查询计划相比,思路相似,小数据规模查询而不是大海捞针。

开端的计划是建一个index,当数据量增大的时分,就扩容增加index的shard的个数,当shards增大时,要查找的shards个数也随之明显上升,依据数据分组的思路,能够依据client进行数据分组,每一个client只需依赖自己的index的数据shards进行查找,而不是一切的数据shards,大大进步了查找的功能,如下图:

ElasticSearch还能性能调优,涨见识、涨见识了!!!

运用Filter代替Query

在查找时分运用Query,需求为Document的相关度打分,运用Filter,没有打分环节处理,做的工作更少,并且filter理论上更快一些。

假如查找不需求打分,能够直接运用filter查询,假如部分查找需求打分,主张运用’bool’查询,这种方法能够把打分的查询和不打分的查询组合在一起运用,如

COPYGET /_search
{
"query": {
"bool": {
"must": {
"term": {
"user": "kimchy"
}
},
"filter": {
"term": {
"tag": "tech"
}
}
}
}
}
ID字段定义为keyword

一般状况,假如ID字段不会被用作Range 类型查找字段,都能够定义成keyword类型,这是由于keyword会被优化,以便进行terms查询,Integers等数字类的mapping类型,会被优化来进行range类型查找,将integers改成keyword类型之后,查找功能大约能进步30%

hot_threads

能够运用以下指令,抓取30s区间内的节点上占用资源的热线程,并经过排查占用资源最多的TOP线程来判别对应的资源耗费是否正常

COPYGET /_nodes/hot_threads&interval=30s

一般状况下,bulk,search类的线程占用资源都或许是事务构成的,可是假如是merge线程占用了许多的资源,就应该考虑是不是创立index或许刷磁盘距离太小,批量写入size太小构成的。

ElasticSearch还能性能调优,涨见识、涨见识了!!!

pending_tasks

有一些任务只能由主节点去处理,比方创立一个新的索引或许在集群中移动分片,由于一个集群中只能有一个主节点,所以只要这一master节点能够处理集群等级的元数据变化

在99.9999%的时刻里,这不会有什么问题,元数据变化的行列基本上保持为零,在一些稀有的集群里,元数据变化的次数比主节点能处理的还快,这会导致等待中的操作会累积成行列,这个时分能够经过pending_tasks api剖析当时什么操作阻塞了es的行列,比方,集群反常时,会有许多的shard在recovery,假如集群在许多创立新字段,会呈现许多的put_mappings的操作,所以正常状况下,需求禁用动态mapping。

COPYGET /_cluster/pending_tasks

ElasticSearch还能性能调优,涨见识、涨见识了!!!

字段存储

当时es首要有doc_values,fielddata,storefield三种类型,大部分状况下,并不需求三种类型都存储,可依据实践场景进行调整:

当时用得最多的便是doc_values,列存储,关于不需求进行分词的字段,都能够敞开doc_values来进行存储(且只保存keyword字段),节省内存,当然,敞开doc_values会对查询功能有必定的影响,可是,这个功能损耗是比较小的,并且是值得的;

fielddata构建和办理 100% 在内存中,常驻于 JVM 内存堆,所以可用于快速查询,可是这也意味着它本质上是不可扩展的,有许多边际状况下要防范,假如关于字段没有剖析需求,能够封闭fielddata;

storefield首要用于_source字段,默许状况下,数据在写入es的时分,es会将doc数据存储_source字段,查询时能够经过_source字段快速获取doc的原始结构,假如没有update,reindex等需求,能够将_source字段disable;

_all,ES在6.x曾经的版别,默许将写入的字段拼接成一个大的字符串,并对该字段进行分词,用于支撑整个doc的全文检索,在知道doc字段称号的状况下,主张封闭掉该字段,节省存储空间,也防止不带字段key的全文检索;

norms:查找时进行评分,日志场景一般不需求评分,主张封闭;

事务日志

Elasticsearch 2.0之后为了确保不丢数据,每次 index、bulk、delete、update 完结的时分,必定会触发同步改写 translog 到磁盘上,才给恳求回来 200 OK

异步改写

选用异步改写,这个改变在进步数据安全性的一起当然也下降了一点功能,假如你不在意这点或许性,仍是希望功能优先,能够在 index template 里设置如下参数

COPY{
    "index.translog.durability": "async"
}
其他参数
index.translog.sync_interval

关于一些大容量的偶尔丢失几秒数据问题也并不严峻的集群,运用异步的 fsync 仍是比较有益的,比方,写入的数据被缓存到内存中,再每5秒履行一次 fsync ,默以为5s,小于的值100ms是不答应的。

index.translog.flush_threshold_size

translog存储尚未安全保存在Lucene中的一切操作,尽管这些操作可用于读取,但假如要封闭并且有必要康复,则需求从头编制索引,此设置操控这些操作的最大总巨细,以防止康复时刻过长,达到设置的最大size后,将产生改写,生成新的Lucene提交点,默以为512mb。

refresh_interval

履行改写操作的频率,这会使索引的最近更改对查找可见,默以为1s,能够设置-1为禁用改写,关于写入速率要求较高的场景,能够适当的加大对应的时长,减小磁盘io和segment的生成;

制止动态mapping

动态mapping的缺陷
  1. 构成集群元数据一向改变,导致 不稳定;
  2. 或许构成数据类型与实践类型不一致;
  3. 关于一些反常字段或许是扫描类的字段,也会频繁的修正mapping,导致事务不可控。
映射装备

动态mapping装备的可选值及意义如下

  • true:支撑动态扩展,新增数据有新的字段特点时,主动增加关于的mapping,数据写入成功
  • false:不支撑动态扩展,新增数据有新的字段特点时,直接疏忽,数据写入成功
  • strict:不支撑动态扩展,新增数据有新的字段时,报错,数据写入失败

批量写入

批量恳求明显会大大进步写入速率,且这个速率是能够量化的,官方主张每次批量的数据物理字节数5-15MB是一个比较不错的起点,注意这儿说的是物理字节数巨细。

文档计数对批量巨细来说不是一个好指标,比方说,假如你每次批量索引 1000 个文档,记住下面的事实:1000 个 1 KB 巨细的文档加起来是 1 MB 大,1000 个 100 KB 巨细的文档加起来是 100 MB 大。

这可是完彻底全不一样的批量巨细了,批量恳求需求在和谐节点上加载进内存,所以批量恳求的物理巨细比文档计数重要得多,从 5–15 MB 开端测验批量恳求巨细,缓慢增加这个数字,直到你看不到功能进步为止。

然后开端增加你的批量写入的并发度(多线程等等方法),用iostat 、 top 和 ps 等东西监控你的节点,观察资源什么时分达到瓶颈。假如你开端收到 EsRejectedExecutionException ,你的集群没方法再持续了:至少有一种资源到瓶颈了,或许削减并发数,或许供给更多的受限资源(比方从机械磁盘换成 SSD),或许增加更多节点。

索引和shard

es的索引,shard都会有对应的元数据,

由于es的元数据都是保存在master节点,且元数据的更新是要hold住集群向一切节点同步的,当es的新建字段或许新建索引的时分,都会要获取集群元数据,并对元数据进行改变及同步,此时会影响集群的呼应,所以需求重视集群的index和shard数量,

运用主张

主张如下

  1. 运用shrink和rollover api,相对生成适宜的数据shard数;
  2. 依据数据量级及对应的功能需求,挑选创立index的称号,形如:按月生成索引:test-YYYYMM,按天生成索引:test-YYYYMMDD;
  3. 操控单个shard的size,正常状况下,日志场景,主张单个shard不大于50GB,线上事务场景,主张单个shard不超越20GB;

段兼并

段兼并的计算量巨大, 并且还要吃掉许多磁盘 I/O

兼并在后台定时操作,由于他们或许要很长时刻才能完结,尤其是比较大的段,这个通常来说都没问题,由于大规模段兼并的概率是很小的。

假如发现merge占用了许多的资源,能够设置:index.merge.scheduler.max_thread_count: 1 特别是机械磁盘在并发 I/O 支撑方面比较差,所以咱们需求下降每个索引并发访问磁盘的线程数,这个设置答应 max_thread_count + 2 个线程一起进行磁盘操作,也便是设置为 1 答应三个线程,关于 SSD,你能够疏忽这个设置,默许是 Math.min(3, Runtime.getRuntime().availableProcessors() / 2) ,对 SSD 来说运转的很好。

事务低峰期经过force_merge强制兼并segment,下降segment的数量,减小内存耗费;封闭冷索引,事务需求的时分再进行敞开,假如一向不运用的索引,能够定时删去,或许备份到hadoop集群;

主动生成_id

当写入端运用特定的id将数据写入es时,es会去检查对应的index下是否存在相同的id,这个操作会跟着文档数量的增加而耗费越来越大,所以假如事务上没有强需求,主张运用es主动生成的id,加速写入速率。

routing

关于数据量较大的事务查询场景,es侧一般会创立多个shard,并将shard分配到集群中的多个实例来分摊压力,正常状况下,一个查询会遍历查询一切的shard,然后将查询到的成果进行merge之后,再回来给查询端。

此时,写入的时分设置routing,能够防止每次查询都遍历全量shard,而是查询的时分也指定对应的routingkey,这种状况下,es会只去查询对应的shard,能够大幅度下降兼并数据和调度全量shard的开销。

运用alias

出产供给服务的索引,牢记运用别号供给服务,而不是直接暴露索引称号,防止后续由于事务改变或许索引数据需求reindex等状况构成事务中止。

防止宽表

在索引中定义太多字段是一种或许导致映射爆炸的状况,这或许导致内存不足过错和难以康复的状况,这个问题或许比预期更常见,index.mapping.total_fields.limit ,默许值是1000

防止稀少索引

由于索引稀少之后,对应的相邻文档id的delta值会很大,lucene依据文档id做delta编码紧缩导致紧缩率下降,然后导致索引文件增大,一起,es的keyword,数组类型选用doc_values结构,每个文档都会占用必定的空间,即便字段是空值,所以稀少索引会构成磁盘size增大,导致查询和写入效率下降。

最终说一句(求重视,别白嫖我)

假如这篇文章对您有所协助,或许有所启发的话,求一键三连:点赞、转发、在看。您的支撑是我坚持写作最大的动力。

  • 作者: 博学谷狂野架构师

  • GitHub地址:GitHub地址 (有咱们精心预备的130本电子书PDF)

本文由传智教育博学谷狂野架构师教研团队发布。

假如本文对您有协助,欢迎重视点赞;假如您有任何主张也可留言谈论私信,您的支撑是我坚持创造的动力。

转载请注明出处!