日期: April 11, 2022

了解es的内存使用分布并进行适当的优化还是有好处的,所以整理了以下内容,常见的优化手段有 段合并/索引冻结/索引生命周期等


ES的heap消耗主要在以下几处地方

segment memory

filter cache

field data cache

bulk queue

indexing buffer

state buffer

内存之segment memory

ES 的 data node 存储数据并非只是耗费磁盘空间的,为了加速数据的访问,每个 segment 都有会一些索引数据驻留在 heap 里

因此 segment 越多,瓜分掉的 heap 也越多,并且这部分 heap 是无法被 GC 掉的,当一个 node 的 segment memory 占用过多的时候,就需要考虑删除、归档数据,或者扩容了

查看segment memory占用情况

  • 查看一个索引所有segment的memory占用情况,重点看size.segment这一列
GET /_cat/segments/index_name?v&h=shard,segment,size,size.segment
  • 查看一个node上所有segment占用的memory总和
GET /_cat/nodes?v&h=name,port,sm

如何减少segment memory占用

  • 删除不用的索引
  • 关闭索引文件仍然存在于磁盘,只是释放掉内存,需要的时候可以重新打开。这里释放的就是前缀索引
  • 段合并定期对不再更新的索引做 force merge api(ES2.0 及更早版本叫做 optimize)。也就是强制段合并,可以节省大量的 segment memory

内存之Indexing Buffer

Indexing Buffer 是用来缓存新数据,当其满了或者 refresh/flush interval 到了,就会以 segment file 的形式写入到磁盘。这个参数的默认值是 10% heap size,建议默认值

内存之Cluster State Buffer

ES 被设计成每个 node 都可以响应用户的 api 请求,因此每个 node 的内存里都包含有一份集群状态的拷贝

这个 cluster state 包含诸如集群有多少个 node,多少个 index,每个 index 的 mapping 是什么?多少 shard,每个 shard 的分配情况等等 (ES 有各类 stats api 获取这类数据)

在一个规模很大的集群,这个状态信息可能会非常大的,耗用的内存空间就不可忽视了

内存之Lucane

Lucene 的设计目的是把底层 OS 里的数据缓存到内存中。Lucene 的段是分别存储到单个文件中的,这些文件都是不会变化的,所以很利于缓存,同时操作系统也会把这些段文件缓存起来,以便更快的访问

Lucene 的性能取决于和 OS 的交互,如果你把所有的内存都分配给 Elasticsearch,不留一点给 Lucene,那你的全文检索性能会很差

官方建议 heap size 不要超过系统可用内存的一半,因为 heap 以外的内存并不会被浪费,Lucene 会利用他们来 cache 被用读取过的段文件

Tips

Jvm内存不要超过32G,jvm 在内存小于 32 G 的时候会采用一个内存对象指针压缩技术,超过 32 G的话,不仅浪费了内存,还降低了 CPU 的性能

什么样的查询会被缓存?对于历史查询次数有要求,对于消耗高昂的Query只需要2次就加入缓存,其他的默认是5次,对于BooleanQuery和DisjunctionMaxQuery次数为4次。默认的,这个历史查询的数量是256