七叶笔记 » golang编程 » 生产级搜索引擎ES性能调优实战

生产级搜索引擎ES性能调优实战

欢迎关注我的头条号:Wooola,10年Java软件开发及架构设计经验,专注于Java、Golang、微服务架构,致力于每天分享原创文章、快乐编码和开源技术。
 

1、所有的修改都可以在elasticsearch.yml里面修改,也可以通过api来修改。推荐用api比较灵活

1.不同分片之间的数据同步是一个很大的花费,默认是1s同步,如果我们不要求实时性,我们可以执行如下:

$ curl -XPUT ' -d '{
 "settings" : {
 "index" : {
 "refresh_interval":"60s"
 }
 }
}'
 

此处我们是修改为60s 其实可以改为-1s 这样就是不刷新,我们需要在查询的时候进行一次索引刷新然后再查询,这个嘛就得看你们用户能容忍多少时间长度了。

2、选择正确的存储

一般来说,如果运行的是64位操作系统,你应该选择mmapfs。如果没有运行64位操作系统,为UNIX系统选择niofs,为Windows系统选择simplefs。如果你可以容忍一个易失的存储,但希望它非常快,可以看看memory存储,它会给你最好的索引访问性能,但需要足够的内存来处理所有索引文件、索引和查询。

3、优化es的 线程

elasticsearch.yml中可以设置 :

threadpool.index.type: fixed
threadpool.index.size: 100
threadpool.index.queue_size: 500
 

当然可以restAPI设置

curl -XPUT 'localhost:9200/_cluster/settings' -d '{
 "transient": {
 "threadpool.index.type": "fixed",
 "threadpool.index.size": 100,
 "threadpool.index.queue_size": 500
 }
}'
 

4、index过于庞大导致es经常奔溃

es最近老是挂掉,无缘无故,表现症状为 对于大小超过100g的index(5个分片 1e数据量左右)插入超级慢,由于机器资源有限 ,只能想出 将每一天的数据建立一个index+“yyyy-MM-dd” 这样可以有效缓解我们集群的压力,有人会说如果改成这种方案那么之前写的查询岂不是废了,其实很easy,es支持index通配符 比如你之前是logment 现在是logment2015-05-01和logment2015-05-02 现在只需要将查询的代码中index改为 logment* 就ok了 ,而且此法便于删除过期的index 写一个定时任务就ok了

我们日志的架构是这样的 logstash(client1) 采集日志到 redis 然后通过 logstash(client2) 从redis转至 elasticsearch ,logstash写入elasticsearch的时候默认就是按照每天来建立索引的 在其配置文件无需指明 index和type 即可。

此处会产生一个问题,就是logstash 自动建立索引的时候是根据格林尼治时间来建立的 正正比我们的时间 迟了8小时,我们需要在logstash的lib里面找到event.rb 然后找到 org.joda.time.DateTimeZone.UTC 格林尼治时间 改成 org.joda.time.DateTimeZone.getDefault() (获取本地时间类型 我这边运行就是中国/上海) 即可 话说logstash用的居然是大名鼎鼎的joda 果然是优秀程序 。

5、采用G1垃圾回收机制代替默认CMS

这里我不分析cms和g1的细节区别,大内存(超过8g)下G1还是很给力的,亲测有效,用了G1 一周内一次FULLGC 都没有,哈哈

elasticsearch.in.sh内将:

# Force the  JVM  to use IPv4 stack
if [ "x$ES_USE_IPV4" != "x" ]; then
 JAVA_OPTS="$JAVA_OPTS -Djava.net.preferIPv4Stack=true"
fi
 
JAVA_OPTS="$JAVA_OPTS -XX:+UseParNewGC"
JAVA_OPTS="$JAVA_OPTS -XX:+UseConcMarkSweepGC"
 
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"
 

大功告成

顺便说句JVM调优,调优最主要目标:1.就是降低 GC 次数时间;2.降低FULLGC 几率

PS:优化代码比优化JVM实在多了

6、清理掉没用的 缓存

回忆之前的问题发现jvm调优对于老年代的回收并没有很显著的效果,随着时间的推移内存还是不够~后来才发现是es cache的问题

其实集群建立时我们是可以调整每隔节点的缓存比例、类型、者大小的

# 锁定内存,不让JVM写入swapping,避免降低ES的性能
bootstrap.mlockall: true
# 缓存类型设置为Soft Reference,只有当内存不够时才会进行回收
index.cache.field.max_size: 50000
index.cache.field.expire: 10m
index.cache.field.type: soft
 

但是如果你不想重新配置节点并且重启,你可以做一个定时任务来定时清除cache

 //清除所有索引的cache,如果对查询有实时性要求,慎用!
 

到了晚上资源空闲的时候我们还能合并优化一下索引

 

截止现在我们es集群有38亿左右数据量,比较稳定~

来源:cnblogs | NPH

相关文章