ElasticSearch性能优化

ElasticSearch在性能优化上分为两大部分,一个是单机的参数优化(这个占大部分),另一个是集群的设置,集群从一定程度上可以看做是多个单机组成的,所以它的调试偏向于集群配置。

写在前面:

我们针对于每个点的调试只说一点,因为官方文档叙述的太繁多,无关紧要的项没必要全列出来,有兴趣的可以自行参考,具体的设置是否开启,开启比例等需要根据业务场景来衡量。

分片数

ES数据存在索引中,一个索引由多个分片组成,每个查询在每个分片的单个线程中执行,也就是可以并行处理多个分片,对同一分片也可以进行多个查询和聚合。
所以我们可以适当的为每个索引设置合理的分片数,来提高查询的并行能力,以此来提高速度
ES中默认是5个分片

案例:400G的索引文件默认分片下,聚合全部数据的一个字段需要4~5s,分片数提升到20片,速度在1s内。

JVM内存值设置

Elasticsearch通过 jvm.options文件中的XmsXmx来设置大小内存

-Xms2g
-Xmx2g

注意:这个内存并非是越大越好

由于JVM自带了zero-based compressed oops(零基压缩优化):

从JDK 1.6 update14开始,64 bit JVM正式支持了 -XX:+UseCompressedOops ,这个可以压缩指针,起到节约内存占用的新参数。
Compressed OOPS,即对象压缩技术,压缩引用到32位,以降低堆的占用空间。Zero Based Compressed OOPS(零基压缩优化)进一步提高了压解压效率。

但是在超过临界值32G内存时,这个优化策略将会失效,通常64位JVM消耗的内存会比32位的大1.5倍,这是因为对象指针在64位架构下,长度会翻倍(事实上当内存到达40-50GB的时候,有效内存才相当于使用Compressed OOPS技术时候的32G内存)

所以,一般设置到32G就可以。

禁止Swap(内存交换)

大多数操作系统都试图尽可能多地使用文件系统缓存,并急切地交换未使用的应用程序内存,可以通俗的理解为:

swap=内存与硬盘交换数据

这种操作对于性能和节点的稳定性都是非常不利的,它会导致垃圾收集持续数分钟而不是毫秒,并且会导致节点响应缓慢甚至断开与集群的连接。
有三种方法来设置swap

停掉本机所有swap
sudo swapoff -a  
降低swappiness优先级
sudo sysctl vm.swappiness = 1  
针对elasticsearch.yml设置内存lock
bootstrap.memory_lock: true

三种方法对应着三种不同范围的定义,权限和范围都是是由大到小,可根据服务器的功能灵活配置。

去掉mapping中_all域

Index中默认会有_all的域,这个会给查询带来方便,但是会增加索引时间和索引数据大小

PUT my_index
{
  "mappings": {
    "type_2": {
      "_all": {
        "enabled": false
      },
      "properties": {...}
    }
  }
}

Cache比例

Indices Cache

索引缓存,用于插数据时

indices.memory.index_buffer_size: 10%
Node Query Cache

节点查询缓存查询,负责缓存查询结果。每个Node上的所有shards都共享一个查询缓存(只针对filter缓存)。缓存实现了LRU驱逐策略;

常用的三种缓存驱逐策略:

1.LRU:最近最少使用的,缓存的元素有一个时间戳,当缓存容量满了,而又需要腾出地方来缓存新的元素的时候,那么现有缓存元素中时间戳离当前时间最远的元素将被清除缓存。
2.LFU:最少被使用,缓存的元素有一个hit属性,hit值最小的将会被清除缓存。
3.FIFO:先进先出。

es采用了LRU驱逐策略

设置Node查询缓存的值,可以在每个Node上单独设置

indices.queries.cache.size:5%
Fielddata Cache

Fielddata Cache主要应用在text类型的字段上,是一个永久存在于堆中的缓存,fielddata 会加载索引中(针对该特定字段的) 所有的文档,它会消耗大量的堆内存,可以在elasticsearch.yml里设置

indices.fielddata.cache.size:60%

由于Fielddata 耗费内存严重但是效率高,所以针对特殊业务场景,可以配置使用。
Fielddata :https://www.elastic.co/guide/en/elasticsearch/reference/6.4/fielddata.html

批量和并发操作

批量操作

批量操作优于单个请求的效率,所以尽可能多的使用批量操作。
但是这里需要大致找到批量请求的最佳大小,一个通用的方法是在具有单个分片的单个节点上运行基准测试。 首先尝试索引100个文件,然后是200,然后是400,等等。 当索引速度开始稳定时,我们便知道达到了数据批量请求的最佳大小。

java批量API:https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/java-docs-bulk.html

并发操作

单个线程发送批量请求不太可能将Elasticsearch集群的性能最大化利用,为了发挥Elasticsearch集群的最大性能,应该从多个线程或进程发送我们的业务请求。 除了更好地利用集群的资源,这应该有助于降低每个fsync的成本。

注意:TOO_MANY_REQUESTS(429)响应代码(Java客户端的EsRejectedExecutionException),这是Elasticsearch告诉我们承受不住这么高频率的请求了。

与批量调整大小请求类似,只有测试才能确定最佳的并发数量。 这可以通过逐渐增加工作者数量来测试,直到集群上的I / OCPU饱和。

调整index.refresh_interval

Elasticsearch 在写入数据时候,采用延迟写入的策略,即数据先写到内存中,当超过默认 1 秒 (index.refresh_interval)会进行一次写入操作,就是将内存中 segment 数据刷新到操作系统中,此时我们才能将数据搜索出来,所以这就是为什么 Elasticsearch 提供的是近实时搜索功能,而不是实时搜索功能。

index.refresh_interval默认是1s,

经常执行刷新合并操作,这使得对搜索可见的索引进行最近的更改。但是也频繁使用了服务器性能,可以把改参数设置为不刷新或者合适的时间间隔

禁用刷新
index.refresh_interval:-1
扩大刷新时间
index.refresh_interval:60s

优化es的线程池

最新版本的es线程池有三种类型:

cache:这是无限制的线程池,为每个传入的请求创建一个线程。
fixed:这是一个有着固定大小的线程池,大小由size属性指定,允许你指定一个队列(使用queue_size属性指定)用来保存请求,直到有一个空闲的线程来执行请求。如果Elasticsearch无法把请求放到队列中(队列满了),该请求将被拒绝。
scaling:缩放线程池拥有动态线程数。这个数字与工作量成正比,并且在核心值和最大值之间变化。

可指定线程池类型的操作

index:此线程池用于索引和删除操作。默认type为fixed,size为可用处理器的数量,size为300。
search:此线程池用于搜索和计数请求。默认type为fixed,size为可用处理器的数量乘以3,size为1000。

get:此线程池用于实时的GET请求。默认为fixed,size为可用处理器的数量,size默认为1000。
bulk:此线程池用于批量操作。默认为fixed,size为可用处理器的数量,size为50。

......
......

elasticsearch.yml中可以设置 :

threadpool.index.type: fixed
threadpool.index.size: 100
threadpool.index.queue_size: 500
thread_pool.get.queue_size
thread_pool.bulk.queue_size
thread_pool.index.queue_size
thread_pool.listener.queue_size
thread_pool.search.queue_size
thread_pool.force_merge.queue_size

G1垃圾回收机制代替默认CMS

cms和g1的区别可以参考https://www.jianshu.com/p/466068ce238d
替换方式为把elasticsearch.in.sh 文件内将

if [ "x$ES_USE_IPV4" != "x" ]; then
  JAVA_OPTS="$JAVA_OPTS -Djava.net.preferIPv4Stack=true"
fi
 
JAVA_OPTS="$JAVA_OPTS -XX:CMSInitiatingOccupancyFraction=75"
JAVA_OPTS="$JAVA_OPTS -XX:+UseCMSInitiatingOccupancyOnly"

替换为

JAVA_OPTS="$JAVA_OPTS -XX:+UseG1GC"
JAVA_OPTS="$JAVA_OPTS -XX:MaxGCPauseMillis=200"

以上就是ElasticSearch性能优化的一些关键点,后续发现欢迎补充

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266