吃透 Elasticsearch 堆内存

标签: dev | 发表时间:2018-04-20 00:00 | 作者:
出处:http://itindex.net/relian

1、什么是堆内存?

Java 中的堆是 JVM 所管理的最大的一块内存空间,主要用于存放各种类的实例对象。
在 Java 中,堆被划分成两个不同的区域:

  • 新生代 ( Young )、

  • 老年代 ( Old )。

新生代 ( Young ) 又被划分为三个区域

  • Eden、

  • From Survivor、

  • To Survivor。

这样划分的目的是为了使 JVM 能够更好的管理堆内存中的对象,包括内存的分配以及回收。

2、堆内存的作用是什么?

在虚拟机启动时创建。

堆内存的 唯一目的就是创建对象实例,所有的对象实例和数组都要在堆上分配。

堆是由垃圾回收来负责的,因此也叫做“GC堆”,垃圾回收采用分代算法,堆由此分为新生代和老年代。

堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,因为它是在运行时动态分配内存的,Java的垃圾收集器会自动收走这些不再使用的数据。

缺点是,由于要在运行时动态分配内存,存取速度较慢。当堆内存因为满了无法扩展时就会抛出java.lang.OutOfMemoryError:Java heap space异常。出现这种情况的解决办法具体参见java调优。

3、堆内存如何配置?

默认情况下,Elasticsearch JVM使用堆内存最小和最大大小为2 GB(5.X版本以上)。

早期版本默认1GB,官网指出:这明显不够。

在转移到生产环境时,配置足够容量的堆大小以确保Elasticsearch功能和性能是必要的。

Elasticsearch将通过Xms(最小堆大小)和Xmx(最大堆大小)设置来分配jvm.options中指定的整个堆。

举例如下:

设置方式一:
在jvm.option配置文件中设置堆内存。

   

1-Xms2g
2-Xmx2g

设置方式二:
通过环境变量设置。
这可以通过注释掉jvm.options文件中的Xms和Xmx设置并通过ES_JAVA_OPTS设置这些值来完成:

   

1ES_JAVA_OPTS="-Xms2g -Xmx2g"./bin/elasticsearch
2ES_JAVA_OPTS="-Xms4000m -Xmx4000m"./bin/elasticsearch

4、堆内存的决定因素

堆内存的值取决于服务器上可用的内存大小。

5、堆内存配置建议

  • 将最小堆大小(Xms)和最大堆大小(Xmx)设置为彼此相等。

  • Elasticsearch可用的堆越多,可用于缓存的内存就越多。但请注意,太多的堆内存可能会使您长时间垃圾收集暂停。

  • 将Xmx设置为不超过物理内存的50%,以确保有足够的物理内存留给内核文件系统缓存。

  • 不要将Xmx设置为JVM超过32GB。

   

1大小建议:
2宿主机内存大小的一半和31GB,取最小值。

6、堆内存为什么不能超过物理机内存的一半?

堆对于Elasticsearch绝对重要
它被许多内存数据结构用来提供快速操作。但还有另外一个非常重要的内存使用者:Lucene。

Lucene旨在利用底层操作系统来缓存内存中的数据结构。 Lucene段(segment)存储在单个文件中。因为段是一成不变的,所以这些文件永远不会改变。这使得它们非常容易缓存,并且底层操作系统将愉快地将热段(hot segments)保留在内存中以便更快地访问。这些段包括倒排索引(用于全文搜索)和文档值(用于聚合)。

Lucene的性能依赖于与操作系统的这种交互。 但是如果你把所有可用的内存都给了Elasticsearch的堆那么Lucene就不会有任何剩余的内存。这会严重影响性能。

标准建议是将可用内存的50%提供给Elasticsearch堆,而将其他50%空闲。它不会被闲置; Lucene会高兴地吞噬掉剩下的东西。

如果您不字符串字段上做聚合操作(例如,您不需要fielddata),则可以考虑进一步降低堆。堆越小,您可以从Elasticsearch(更快的GC)和Lucene(更多内存缓存)中获得更好的性能。

7、堆内存为什么不能超过32GB?

在Java中,所有对象都分配在堆上并由指针引用。普通的对象指针(OOP)指向这些对象,传统上它们是CPU本地字的大小:32位或64位,取决于处理器。

对于32位系统,这意味着最大堆大小为4 GB。对于64位系统,堆大小可能会变得更大, 但是64位指针的开销意味着仅仅因为指针较大而存在更多的浪费空间。并且比浪费的空间更糟糕,当在主存储器和各种缓存(LLC,L1等等)之间移动值时,较大的指针 消耗更多的带宽

Java使用称为压缩oops的技巧来解决这个问题。而不是指向内存中的确切字节位置,指针引用对象偏移量。这意味着一个32位指针可以引用40亿个对象,而不是40亿个字节。最终,这意味着堆可以增长到约32 GB的物理尺寸,同时仍然使用32位指针。

一旦你穿越了这个神奇的〜32 GB的边界,指针就会切换回普通的对象指针。每个指针的大小增加,使用 更多的CPU内存带宽,并且实际上会丢失内存。实际上,在使用压缩oops获得32 GB以下堆的相同有效内存之前,需要大约40-50 GB的分配堆。

以上小结为: 即使你有足够的内存空间,尽量避免跨越32GB的堆边界
否则会导致浪费了内存,降低了CPU的性能,并使GC在大堆中挣扎。

8、我是内存土豪怎么办?

   

1假设,我有一台带有1TB RAM的机器!

32 GB的基线相当重要。那么当你的机器有很多内存时你怎么做?当前具有512-768 GB RAM的超级服务器变得越来越普遍。

首先,我们建议避免使用这种大型机器。

但是如果你已经有了这些机器,你有三种实用的选择:

1. 你是否主要进行全文搜索?

考虑给Elasticsearch提供4-32 GB,并让Lucene通过操作系统文件系统缓存使用剩余的内存。所有内存都会缓存段,并导致快速全文搜索。

2. 你在做很多排序/聚合?

大部分聚合数字,日期,地理位置和not_analyzed字符串?你很幸运,你的聚合将在内存缓存的文档值上完成!

从4-32 GB的内存中给Elasticsearch一个地方,剩下的让操作系统在内存中缓存doc值。

3. 你是否对分析过的字符串进行了很多排序/聚合(例如对于字标记或SigTerms等)?

  • 不幸的是,这意味着你需要fielddata,这意味着你需要堆空间。

  • 考虑在一台机器上运行两个或多个节点,而不是一个节点数量巨大的RAM。

  • 尽管如此,仍然坚持50%的规则。

To土豪内存小结:

  • 因此,如果您的机器具有128 GB的RAM,请运行两个节点,每个节点的容量低于32 GB。这意味着小于64 GB将用于堆,而Lucene将剩余64 GB以上。

  • 如果您选择此选项,请在您的配置中设置cluster.routing.allocation.same_shard.host:true。这将阻止主副本分片共享同一台物理机(因为这会消除副本高可用性的好处)。

9、堆内存优化建议

方式一:最好的办法是在系统上完全禁用交。
这可以暂时完成:

   

1sudoswapoff -a

要永久禁用它,你可能需要编辑你的/ etc / fstab。

方式二:控制操作系统尝试交换内存的积极性。

如果完全禁用交换不是一种选择,您可以尝试降低swappiness。该值控制操作系统尝试交换内存的积极性。这可以防止在正常情况下交换,但仍然允许操作系统在紧急内存情况下进行交换。

对于大多数Linux系统,这是使用sysctl值配置的:

   

1vm.swappiness = 1

1的swappiness优于0,因为在某些内核版本上,swappiness为0可以调用OOM杀手。

方式三:mlockall允许JVM锁定其内存并防止其被操作系统交换。

最后,如果两种方法都不可行,则应启用mlockall。文件。这允许JVM锁定其内存并防止其被操作系统交换。在你的elasticsearch.yml中,设置这个:

   

1bootstrap.mlockall:true

10、注意

  • 修改JVM相关配置很容易,但容易产生难以测量的不透明效果,并最终将您的群集解调为缓慢,不稳定的混乱

  • 在调试群集时,第一步通常是删除所有自定义配置。大约一半的时间,仅靠这一点就恢复了稳定性和性能。

11、最新认知

wood@Ctrip
事实上,给ES分配的内存有一个魔法上限值 26GB

这样可以确保启用zero based Compressed Oops,这样性能才是最佳的。

参考:https://elasticsearch.cn/question/3995
https://www.elastic.co/blog/a-heap-of-trouble

12、小结

这是一篇官网文档&原理的整合文章,主要目的是梳理认知。

切记:宿主机内存大小的一半和31GB,取最小值。

13、参考

  • 基础:http://t.cn/RH4DDYu

  • 设置:http://t.cn/RmKbO1i

  • 建议:http://t.cn/RmKbjsF

  • 注意:http://t.cn/RmKbHp5

  • 堆:http://t.cn/RmKbRji

    加入星球,更短时间,更快习得更多干货!



相关 [elasticsearch 内存] 推荐:

Elasticsearch 合理内存分配

- - 开源软件 - ITeye博客
Elasticsearch默认安装后设置的内存是1GB,对于任何一个业务部署来说,这个都太小了. 如果你正在使用这些默认堆内存配置,你的集群配置可能有点问题. 这里有两种方式修改Elasticsearch的堆内存(下面就说内存好了),最简单的一个方法就是指定ES_HEAP_SIZE环境变量. 服务进程在启动时候会读取这个变量,并相应的设置堆的大小.

吃透 Elasticsearch 堆内存

- - IT瘾-dev
Java 中的堆是 JVM 所管理的最大的一块内存空间,主要用于存放各种类的实例对象. 在 Java 中,堆被划分成两个不同的区域:. 新生代 ( Young )、. 新生代 ( Young ) 又被划分为三个区域. 这样划分的目的是为了使 JVM 能够更好的管理堆内存中的对象,包括内存的分配以及回收.

腾讯万亿级 Elasticsearch 内存效率提升技术解密

- - IT瘾-dev
作者:morningchen,腾讯 TEG 后台开发工程师. Elasticsearch( ES )是一款功能强大的开源分布式实时搜索引擎,在日志分析(主要应用场景)、企业级搜索、时序分析等领域有广泛应用,几乎是各大公司搜索分析引擎的开源首选方案. Tencent ES 是内核级深度优化的 ES 分支,持续地进行高可用、高性能、低成本等全方位优化,已支撑的单集群规模达到千级节点、万亿级吞吐.

[译]elasticsearch mapping

- - an74520的专栏
es的mapping设置很关键,mapping设置不到位可能导致索引重建. 请看下面各个类型介绍^_^. 每一个JSON字段可以被映射到一个特定的核心类型. JSON本身已经为我们提供了一些输入,支持 string,  integer/ long,  float/ double,  boolean, and  null..

Elasticsearch as Database - taowen - SegmentFault

- -
【北京上地】滴滴出行基础平台部招聘 Elasticsearch 与 Mysql binlog databus 开发工程师. 内推简历投递给: [email protected]. 推销Elasticsearch. 时间序列数据库的秘密(1)—— 介绍. 时间序列数据库的秘密(2)——索引.

ElasticSearch 2 的节点调优(ElasticSearch性能)

- - 行业应用 - ITeye博客
一个ElasticSearch集群需要多少个节点很难用一种明确的方式回答,但是,我们可以将问题细化成一下几个,以便帮助我们更好的了解,如何去设计ElasticSearch节点的数目:. 打算建立多少索引,支持多少应用. elasticsearch版本: elasticsearch-2.x. 需要回答的问题远不止以上这些,但是第五个问题往往是容易被我们忽视的,因为单个ElasticSearch集群有能力支持多索引,也就能支持多个不同应用的使用.

Elasticsearch:使用 Elasticsearch 进行语义搜索

- - 掘金 后端
在数字时代,搜索引擎在通过浏览互联网上的大量可用信息来检索数据方面发挥着重要作用. 此方法涉及用户在搜索栏中输入特定术语或短语,期望搜索引擎返回与这些确切关键字匹配的结果. 虽然关键字搜索对于简化信息检索非常有价值,但它也有其局限性. 主要缺点之一在于它对词汇匹配的依赖. 关键字搜索将查询中的每个单词视为独立的实体,通常会导致结果可能与用户的意图不完全一致.

elasticsearch的javaAPI之query

- - CSDN博客云计算推荐文章
elasticsearch的javaAPI之query API. the Search API允许执行一个搜索查询,返回一个与查询匹配的结果(hits). 它可以在跨一个或多个index上执行, 或者一个或多个types. 查询可以使用提供的 query Java API 或filter Java API.

Elasticsearch基础教程

- - 开源软件 - ITeye博客
转自:http://blog.csdn.net/cnweike/article/details/33736429.     Elasticsearch有几个核心概念. 从一开始理解这些概念会对整个学习过程有莫大的帮助.     接近实时(NRT).         Elasticsearch是一个接近实时的搜索平台.

ElasticSearch索引优化

- - 行业应用 - ITeye博客
ES索引的过程到相对Lucene的索引过程多了分布式数据的扩展,而这ES主要是用tranlog进行各节点之间的数据平衡. 所以从上我可以通过索引的settings进行第一优化:. 这两个参数第一是到tranlog数据达到多少条进行平衡,默认为5000,而这个过程相对而言是比较浪费时间和资源的. 所以我们可以将这个值调大一些还是设为-1关闭,进而手动进行tranlog平衡.