ElasticSearch在性能优化上分为两大部分,一个是单机的参数优化(这个占大部分),另一个是集群的设置,集群从一定程度上可以看做是多个单机组成的,所以它的调试偏向于集群配置。
写在前面:
我们针对于每个点的调试只说一点,因为官方文档叙述的太繁多,无关紧要的项没必要全列出来,有兴趣的可以自行参考,具体的设置是否开启,开启比例等需要根据业务场景来衡量。
JVM内存值设置
Elasticsearch通过 jvm.options文件中的Xms
和 Xmx
来设置大小内存
-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
三种方法对应着三种不同范围的定义,权限和范围都是是由大到小,可根据服务器的功能灵活配置。
Cache比例
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 / O
或CPU
饱和。
调整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
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性能优化的一些关键点,后续发现欢迎补充
网友评论