Elasticesearch内存详解(三)——Segments Memory

简介: 介绍elasticsearch的segment

1.segment介绍image.png

一个segment是一个完备的lucene倒排索引,而倒排索引是通过词典 (Term Dictionary)到文档列表(Postings List)的映射关系,快速做查询的。 由于词典的size会很大,全部装载到heap里不现实,因此Lucene为词典做了一层前缀索引(Term Index),这个索引在Lucene4.0以后采用的数据结构是FST (Finite State Transducer)。 这种数据结构占用空间很小,Lucene打开索引的时候将其全量装载到内存中,加快磁盘上词典查询速度的同时减少随机磁盘访问次数。

segments FST数据的缓存,为了加速查询,FST 永驻堆内内存,无法被 GC 回收。该部分内存无法设置大小,长期占用 50% ~ 70% 的堆内存,只能通过delete index,close index以及force-merge index释放内存

解释下FST:

ES 底层存储采用 Lucene(搜索引擎),写入时会根据原始数据的内容,分词,然后生成倒排索引。查询时,先通过  查询倒排索引找到数据地址(DocID)),再读取原始数据(行存数据、列存数据)。但由于 Lucene 会为原始数据中的每个词都生成倒排索引,数据量较大。所以倒排索引对应的倒排表被存放在磁盘上。这样如果每次查询都直接读取磁盘上的倒排表,再查询目标关键词,会有很多次磁盘 IO,严重影响查询性能。为了解磁盘 IO 问题,Lucene 引入排索引的二级索引 FST [Finite State Transducer] 。原理上可以理解为前缀树,加速查询。

ES的data node存储数据并非只是耗费磁盘空间的,为了加速数据的访问,每个segment都有会一些索引数据驻留在heap里。因此segment越多,瓜分掉的heap也越多,并且这部分heap是无法被GC掉的! 理解这点对于监控和管理集群容量很重要,当一个node的segment memory占用过多的时候,就需要考虑删除、归档数据,或者扩容了。

image.png

2.查看segment

  1. 查看一个索引所有segment的memory占用情况:

curl -X GET "http://127.0.0.1:9200/_cat/segments/index?v&h=shard,segment,size,size.menory"

image.png

  1. 查看一个node上所有segment占用的memory总和:

curl -X GET "http://127.0.0.1:9200/_cat/nodes?h=name,hp,hm,rp,rm,qcm,rcm,fm,sm&v"

image.png

3.segment合并

我们已经知道在elasticsearch中每个shard每隔1秒都会refresh一次,每次refresh都会生成一个新的segment,按照这个速度过不了多久segment的数量就会爆炸,所以存在太多的segment是一个大问题,因为每一个segment都会占用文件句柄,内存资源,cpu资源,更加重要的是每一个搜索请求都必须访问每一个segment,这就意味着存在的segment越多,搜索请求就会变的更慢。


那么elaticsearch是如何解决这个问题呢? 实际上elasticsearch有一个后台进程专门负责segment的合并,它会把小segments合并成更大的segments,然后反复这样。在合并segments的时候标记删除的document不会被合并到新的更大的segment里面,所有的过程都不需要我们干涉,es会自动在索引和搜索的过程中完成,合并的segment可以是磁盘上已经commit过的索引,也可以在内存中还未commit的segment:


(1)在索引时refresh进程每秒会创建一个新的segment并且打开它使得搜索可见


(2)merge进程会在后台选择一些小体积的segments,然后将其合并成一个更大的segment,这个过程不会打断当前的索引和搜索功能。

1654659420110.png



(3)一旦merge完成,旧的segments就会被删除,流程如下:


3.1 新的segment会被flush到磁盘

3.2 然后会生成新的commit point文件,包含新的segment名称,并排除掉旧的segment和那些被合并过的小的segment

3.3 接着新的segment会被打开用于搜索

3.4 最后旧的segment会被删除掉

1654659435540.png


至此原来标记伪删除的document都会被清理掉,如果不加控制,合并一个大的segment会消耗比较多的io和cpu资源,同时也会搜索性能造成影响,所以默认情况下es已经对合并线程做了资源限额以便于它不会搜索性能造成太大影响。


api如下:


PUT /_cluster/settings

{

   "persistent" : {

       "indices.store.throttle.max_bytes_per_sec" : "100mb"

   }

}

或者不限制:


PUT /_cluster/settings

{

   "transient" : {

       "indices.store.throttle.type" : "none"

   }

}

es的api也提供了我们外部发送命令来强制合并segment,这个命令就是optimize,它可以强制一个shard合并成指定数量的segment,这个参数是:max_num_segments ,一个索引它的segment数量越少,它的搜索性能就越高,通常会optimize成一个segment。需要注意的是optimize命令不要用在一个频繁更新的索引上面,针对频繁更新的索引es默认的合并进程就是最优的策略,optimize命令通常用在一个静态索引上,也就是说这份索引没有写入操作只有查询操作的时候是非常适合用optimize来优化的,比如说我们的一些日志索引,基本都是按天,周,或者月来索引的,只要过了今天,这周或这个月就基本没有写入操作了,这个时候我们就可以通过optimize命令,来强制合并每个shard上索引只有一个segment,这样查询性能就能大大提升,api如下:


POST /logstash-2014-10/_optimize?max_num_segments=1

注意,由外部发送的optimize命令是没有限制资源的,也就是你系统有多少IO资源就会使用多少IO资源,这样可能导致某一段时间内搜索没有任何响应,所以如果你计划要optimize一个超大的索引,你应该使用shard allocation功能将这份索引给移动到一个指定的node机器上,以确保合并操作不会影响其他的业务或者es本身的性能。


4.减少内存的办法

  • 删除不用的索引。delete index
  • 关闭索引(文件仍然存在于磁盘,只是释放掉内存),需要的时候可重新打开。close index
  • 定期对不再更新的索引做force merge
相关文章
|
3月前
|
Python
什么是Python中的内存池(Memory Pool)?
什么是Python中的内存池(Memory Pool)?
37 0
|
3月前
|
数据库 数据库管理 Python
解释Python中的内存视图(Memory View)。
解释Python中的内存视图(Memory View)。
|
6天前
|
缓存 Java 开发工具
OOM out of memory 内存溢出
OOM out of memory 内存溢出
14 1
|
26天前
|
JavaScript 前端开发
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 内存溢出问题
FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 内存溢出问题
18 1
|
4月前
|
存储 缓存 Java
Java内存模型(Java Memory Model,JMM)
Java内存模型(Java Memory Model,JMM)
24 0
|
5月前
|
存储 Java C#
C# | 使用Memory<T>高效地读写内存数据
Memory<T>是什么? 它是一种可变大小、可读写的内存块,可以安全地暴露给用户代码进行操作。 为什么要使用Memory<T>? 使用它有许多好处。最主要的是善用它可以提高代码的性能。因为Memory<T>是可变的,所以我们可以直接在内存中操作数据,而不需要进行额外的拷贝操作。 使用Memory<T>还可以减少垃圾回收的压力,因为我们不需要创建新的对象来存储数据。 Memory<T>还可以与Span<T>和ReadOnlySpan<T>类型一起使用,这些类型可以方便地对数据进行访问和操作。
38 0
|
7月前
|
SQL 人工智能 移动开发
Memory Analyzer(MAT)分析内存
MAT是Memory Analyzer tool的缩写,是一款非常强大的内存分析工具,只需要打开采集的hprof文件即可开始对内存开始分析对比,一款“傻瓜式“的堆转储文件分析工具,谁都能学会。
|
8月前
|
SQL 数据库
使用 SAP ABAP Memory Inspector 对应用程序消耗内存进行检测时常犯的错误试读版
使用 SAP ABAP Memory Inspector 对应用程序消耗内存进行检测时常犯的错误试读版
69 0
|
8月前
ABAP Memory Inspector 里对动态内存对象的内存消耗度量方式
ABAP Memory Inspector 里对动态内存对象的内存消耗度量方式
47 0
|
8月前
|
Web App开发 缓存 JavaScript
使用 Chrome 开发者工具的 Memory 标签页分析内存泄漏问题
使用 Chrome 开发者工具的 Memory 标签页分析内存泄漏问题
179 0