不要碰这些配置!edit

在 Elasticsearch 中有几个热点,人们似乎无法避免的要去调整。 我们理解的,所有的调整就是为了优化,但是这些调整,你真的不用去管。因为它们经常会被乱用,从而造成系统的不稳定或者糟糕的性能,甚至两者都有可能。

垃圾回收器 (Garbage Collector)edit

前面已经在垃圾回收入门中简要介绍了,JVM 使用一个垃圾回收器来释放不再使用的内存。 这个提示实际上是对上一个提示的扩展,但是值得强调的是:

不要更改默认的垃圾回收器!

Elasticsearch 默认的垃圾回收器(GC)是 Concurrent-Mark and Sweep (CMS)。 这个垃圾回收器可以和应用并行处理,以便它可以最小化停顿。 然而,它有两个 停止一切(stop-the-world) 阶段,回收很大的堆内存也有点吃力。

尽管有这些缺点,它还是目前对于像 Elasticsearch 这样低延迟需求软件的最佳垃圾回收器。官方建议使用 CMS。

现在有一个新的垃圾回收器,叫 G1垃圾回收器(Garbage First GC, G1GC )。 这款新 GC 的设计旨在最小化暂停时间, 甚至比 CMS 还要小,并具有对大内存的处理能力。 它的工作方式是将堆内存划分成很多区域,并预测哪些区域包含最有可能收回的空间。 通过优先收集这些区域(垃圾优先, garbage first), 可以最小化暂停时间,并能在非常大的堆内存上运行。

听起来很棒!遗憾的是,G1GC 还是太新了,经常发现新的 bug。 这些错误通常属于分段(segfault)故障类型,并会导致硬崩溃(hard crash)。 Lucene 的测试套件对垃圾回收算法要求严格,看起来这些缺陷 G1GC 并没有很好地解决。

我们希望有一天会推荐使用 G1GC,但就目前而言,它还不够稳定,无法满足 Elasticsearch 和 Lucene 的要求。

线程池 (Threadpools)edit

许多人 喜欢 调整线程池。 无论什么原因,人们都对增加线程数无法抗拒。 索引太多了?增加线程!搜索太多了?增加线程!节点空闲率95%?增加线程!

Elasticsearch 默认的线程设置已经是很合理的了。对于所有的线程池(除了 搜索(search) ),线程个数是根据 CPU 核心数设置的。 如果你有 8 个核,你可以同时运行的线程只有 8 个,只给任何特定的线程池分配 8 个线程是有意义的。

搜索(search)线程池设置的大一点,配置为 int((核心数 * 3) / 2) + 1

你可能会认为某些线程可能会阻塞(如磁盘上的 I/O 操作),所以你才想加大线程的。 对于 Elasticsearch 来说这并不是一个问题:因为大多数 I/O 操作是由 Lucene 管理的线程处理的,而不是 Elasticsearch。

此外,线程池通过相互传递工作进行协作。 你不必再因为它正在等待磁盘写操作而担心网络线程阻塞, 因为网络线程早已把这个工作交给另外的线程池,并返回到网络中。

最后,你的处理器的计算能力是有限的,拥有更多的线程会导致你的处理器频繁切换线程上下文。 一个处理器同时只能运行一个线程,所以当它需要切换到一个不同的线程时,它会存储当前的状态(寄存器等等),然后加载另外一个线程。 如果幸运的话,这个切换发生在同一个核心。如果不幸的话,这个切换可能发生在不同的核心,这就需要在内核总线上进行传输。

这个上下文的切换,会给 CPU 时钟周期带来管理调度的开销;在现代的 CPU 上,开销估计高达 30 μs。 也就是说,除非线程被阻塞超过 30 μs,否则很可能时间会更好的花在处理上,并提前完成。

人们经常稀里糊涂的设置线程池的值。8 核的 CPU,我们遇到过有人配了 60、100 甚至 1000 个线程。 这些设置只会让 CPU 瞎忙活,而不是去完成真正的工作。

所以,下此如果你想调整线程池的线程数,请不要这样做。如果你真的无法拒绝 , 一定要关注你的 CPU 核心数,最多设置成核心数的两倍,再多了都是浪费。