我们在使用Kibana构建了一个20+ visulization的dashboard后,终于出现了性能了,问题可能表现为:
- Elasticsearch后台报Java Heap Limit爆了
- Elasticsearch后台报out of memory
- 15分钟时长(每秒1,000条左右)的日志在kibana dashboard要load好几分钟
- 更多的数据会报shard无法获取
在通读了ElasticSearch官方指南中关于性能和调优的页面以后,用中文总结一下ES开发人员关于调优的基本指引:
曾经有很多人以为调个参数就能让性能快个10倍100倍,他们以为我们傻吗?所有能调的我们都给你们调好,别乱动,我们见过数以百计的项目因为乱动参数被钉在了历史的耻辱柱上!性能不够就加机器!
即使这样,还是有极个别的东西我们可以根据部署和ELK的特点微调一下(因为没钱开那多instance)。
Heap Memory
- 不要使用8G内存以下的实例,实在没法用。16G, 32G, 64G都可以。
- 将Heap设置为内存的一半,剩下的lucene要用的
- 不要超过32G
Field data vs docValue
Field data中文名字叫正排索引,也就是以文档为key。原因是主索引不能很好的完成aggregayion和filering这种操作。要注意,fieldData一旦load,会把整个index中的文档都load入Heap,以便于等会要用。 DocValues同样是正排索引,不同的是,DocValues是在索引时构建并存在硬盘的,而不是像field data一样在search时load进内存。可想而知,DocVaule使用性能兑换了对资源的需求。但事实上,根据我找到的一份资料,Docvalue在查询时的性能仅比field data慢20%,而对内存几乎没有需求了。
- 尽量使用docValues
- 将logstash升级到2.0以上并重新构建logstash-*的mapping,logstash会自动将所有raw字段设为
docValues = true
Field data的内存占用
默认条件下,fieldData是不受限的,它虽然放置在内存中,但本质上不是一个transient的缓存,ES也不会丢弃任何内存中的fieldData。在aggregation特别多的时候,这种设定会导致新的fieddata因为内存满了而搜索不到。
有以下几个参数和field data的内存使用有关:
-
a. indices.breaker.fielddata.limit fieldData使用保险;默认60%;
-
b. indices.breaker.request.limit 其他操作(创建buckets什么的)保险;默认40%; 尽量a+b=100%
-
c. indices.breaker.total.limit 总阀;默认80%,应略低于100%;
-
d. indices.fielddata.cache.size 内存回收的触发线,应低于a;
- 使用Elatico的Marvel观测field data在内存中的使用状况,marvel现在是免费的。
index时的性能
Logstash的elaticsearch插件是有默认的批量flush的,默认应该是每500条日志或每1秒,可以适当调整,但默认设置应该不会给ES太大压力。 如果发现日志不能及时进入ES,更有可能的性能问题出在logstash上。Logstash,尤其当期有grok这样的filter时,是可以非常占CPU的。我们的结果是,1秒1000条日志,1个grokfilter,这样的logstash就基本要占用AWS instance的一个核。
- 请意识到解析和索引日志是非常占资源的,请分配足够的资源给logstash。