1. Elasticsearch在Linux上的设置优化

  • 内存方面 64 GB 是最理想化的,但是实际生产中 32 GB 和 16 GB 的服务器也很常见,少于 8GB 最好再和运维部门谈一谈资源的问题;
  • 如果你要在更快的 CPUs 和更多的核心之间选择,选择更多的核心更好。多个内核提供的额外并发远胜过稍微快一点点的时钟频率;
  • 如果公司负担得起 SSD,那么SSD 是一个好的选择,它的传输效率远远超出其他磁盘,基于 SSD 的节点,查询和索引性能都有提升;
  • 即使数据中心近在咫尺,也要避免集群跨越多个数据中心;绝对要避免集群跨越大的地理距离;
  • 要确保运行应用程序的 JVM 和服务器的 JVM 是完全一样的,在 Elasticsearch 的几个地方,使用 Java 的本地序列化;
  • 通过设置gateway.recover_after_nodesgateway.expected_nodesgateway.recover_after_time可以在集群重启的时候避免过多的分片交换,这可能会让数据恢复从数个小时缩短为几秒钟;
  • Elasticsearch 默认被配置为使用单播发现,以防止节点无意中加入集群。只有在同一台机器上运行的节点才会自动组成集群,最好使用单播代替组播;
  • 不要随意修改垃圾回收器(CMS)和各个线程池的大小;
  • 把你的内存的(少于)一半给 Lucene(但不要超过 32GB),通过ES_HEAP_SIZE环境变量设置;
  • 内存交换到磁盘对服务器性能来说是致命的,如果内存交换到磁盘上,一个 100 微秒的操作可能变成 10 毫秒,再想想那么多 10 微秒的操作时延累加起来。 不难看出 swapping 对于性能来说是多么可怕;
  • Lucene 使用了大量的文件,同时,Elasticsearch 在节点和 HTTP 客户端之间进行通信也使用了大量的套接字,所有这一切都需要足够的文件描述符,你应该增加你的文件描述符,设置一个很大的值,如 64000;

补充:索引阶段性能提升方法

  • 使用批量请求并调整其大小:每次批量数据 5-15 MB 大是个不错的起始点;
  • 存储:使用 SSD;
  • 段和合并:Elasticsearch 默认值是 20MB/s,对机械磁盘应该是个不错的设置,如果用的是 SSD,可以考虑提高到 100-200 MB/s。如果你在做批量导入,完全不在意搜索,你可以彻底关掉合并限流。另外还可以增加index.translog.flush_threshold_size设置,从默认的 512MB 到更大一些的值,比如 1GB,这可以在一次清空触发的时候在事务日志里积累出更大的段;
  • 如果你的搜索结果不需要近实时的准确度,考虑把每个索引的index.refresh_interval改到 30s;
  • 如果你在做大批量导入,考虑通过设置index.number_of_replicas: 0关闭副本;

2. Elasticsearch在GC上的注意事项

  • 倒排词典的索引需要常驻内存,无法 GC,需要监控 data node 上 segment memory 增长趋势;
  • 各类缓存,field cache, filter cache, indexing cache, bulk queue 等等,要设置合理的大小,并且要应该根据最坏的情况来看 heap 是否够用,也就是各类缓存全部占满的时候,还有 heap 空间可以分配给其他任务吗?避免采用 clear cache 等 “自欺欺人” 的方式来释放内存;
  • 避免返回大量结果集的搜索与聚合,确实需要大量拉取数据的场景,可以采用 scan & scroll api 来实现;
  • cluster stats 驻留内存并无法水平扩展,超大规模集群可以考虑分拆成多个集群通过 tribe node 连接;
  • 想知道 heap 够不够,必须结合实际应用场景,并对集群的 heap 使用情况做持续的监控;