Elasticsearch默认安装后设置的内存是1GB,对于任何一个业务部署来说,这个都太小了。如果你正在使用这些默认堆内存配置,你的集群配置可能有点问题。

这里有两种方式修改Elasticsearch的堆内存(下面就说内存好了),最简单的一个方法就是指定ES_HEAP_SIZE环境变量。服务进程在启动时候会读取这个变量,并相应的设置堆的大小。举例,你可以用下面的命令设置它

export ES_HEAP_SIZE=10g

此外,你也可以通过命令行参数的形式,在程序启动的时候把内存大小传递给它:

./bin/elasticsearch -Xmx10g -Xms10g

备注:确保Xmx和Xms的大小是相同的,防止程序在运行时改变大小,这个是很废的。

一般来说设置ES_HEAP_SIZE环境变量,比直接写-Xmx10g -Xms10g更好一点。

把你的内存的一半给Lucene

一个常见的问题是配置一个大内存,假设你有一个64G内存的机器,我的天,你想把64G内存给Elasticsearch吗? 越大越好!

当然,内存对于Elasticsearch来说绝对是重要的,用于更多的内存数据提供更快的操作。而且还有一个内存消耗大户-Lucene

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

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

最后标准的建议是把50%的内存给elasticsearch,剩下的50%也不会没有用处的,Lucene会很快吞噬剩下的这部分内存。

不要超过32G

这里有另外一个原因不分配大内存给Elasticsearch,事实上jvm在内存小于32G的时候会采用一个内存对象指针压缩技术。

在java中,所有的对象都分配在堆上,然后有一个指针引用它。指向这些对象的指针大小通常是CPU的字长的大小,不是32bit就是64bit,这取决于你的处理器,指针指向了你的值的精确位置。

对于32位系统,你的内存最大可使用4G。对于64系统可以使用更大的内存。但是64位的指针意味着更大的浪费,因为你的指针本身大了。浪费内存不算,更糟糕的是,更大的指针在主内存和缓存器(例如LLC, L1等)之间移动数据的时候,会占用更多的带宽。

java 使用一个叫内存指针压缩的技术来解决这个问题。它的指针不再表示对象在内存中的精确位置,而是表示偏移量。这意味着32位的指针可以引用40亿个对象,而不是40亿个字节。最终,也就是说堆内存长到32G的物理内存,也可以用32bit的指针表示。

一旦你越过那个神奇的30-32G的边界,指针就会切回普通对象的指针,每个对象的指针都变长了,就会使用更多的CPU内存带宽,也就是说你实际上失去了更多的内存。事实上当内存到达40-50GB的时候,有效内存才相当于使用内存对象指针压缩技术时候的32G内存。

这段描述的意思就是说:即便你有足够的内存,也尽量不要超过32G,因为它浪费了内存,降低了CPU的性能,还要让GC应对大内存。

*我有一个1TB内存的机器
这个32GB的线是很很重要的,那如果你的机器有很大的内存怎么办呢?现在的机器内存普遍增长,你现在都可以看到有300-500GB内存的机器。
首先,我们建议编码使用这样的大型机
其次,如果你已经有了这样的机器,你有两个可选项:
>你主要做全文检索吗?考虑给Elasticsearch 32G内存,剩下的交给Lucene用作操作系统的文件系统缓存,所有的segment都缓存起来,会加快全文检索。
>你需要更多的排序和聚合?你希望更大的堆内存。你可以考虑一台机器上创建两个或者更多ES节点,而不要部署一个使用32+GB内存的节点。仍然要坚持50%原则,假设 你有个机器有128G内存,你可以创建两个node,使用32G内存。也就是说64G内存给ES的堆内存,剩下的64G给Lucene。
如果你选择第二种,你需要配置cluster.routing.allocation.same_shard.host:true。这会防止同一个shard的主副本存在同一个物理机上(因为如果存在一个机器上,副本的高可用性就没有了)。

swapping是性能的坟墓

这是显而易见的,但是还是有必要说的更清楚一点,内存交换到磁盘对服务器性能来说是致命的。想想看一个内存的操作必须是快速的。

如果内存交换到磁盘上,一个100微秒的操作可能变成10毫秒,再想想那么多10微秒的操作时延累加起来。不难看出swapping对于性能是多么可怕。

最好的办法就是在你的操作系统中完全禁用swapping。这样可以暂时禁用:
sudo swapoff -a

为了永久禁用它,你可能需要修改/etc/fstab文件,这要参考你的操作系统相关文档。

如果完全禁用swap,对你来说是不可行的。你可以降低swappiness 的值,这个值决定操作系统交换内存的频率。这可以预防正常情况下发生交换。但仍允许os在紧急情况下发生交换。

对于大部分Linux操作系统,可以在sysctl 中这样配置:
vm.swappiness = 1
备注:swappiness设置为1比设置为0要好,因为在一些内核版本,swappness=0会引发OOM(内存溢出)

最后,如果上面的方法都不能做到,你需要打开配置文件中的mlockall开关,它的作用就是运行JVM锁住内存,禁止OS交换出去。在elasticsearch.yml配置如下:
bootstrap.mlockall: true

原文地址:https://www.elastic.co/guide/en/elasticsearch/guide/current/heap-sizing.html.

[翻译]Elasticsearch重要文章之二:堆内存的大小和swapping的更多相关文章

  1. [翻译]Elasticsearch重要文章之四:监控每个节点(jvm部分)

    http://zhaoyanblog.com/archives/753.html 操作系统和进程部分 操作系统和进程部分的含义是很清楚的,这里不会描述的很详细.他们列出了基本的资源统计,例如CPU和负 ...

  2. 关于ElasticSearch的堆内存设置与优化

    1.什么是堆内存?Java 中的堆是 JVM 所管理的最大的一块内存空间,主要用于存放各种类的实例对象.在 Java 中,堆被划分成两个不同的区域:- 新生代 ( Young ).- 老年代 ( Ol ...

  3. docker启动 elasticsearch 修改 xmx xms 堆内存大小修改

    用docker 安装的elasticsearch 5.6版本默认堆内存最大设置的2G 可以通过如下方法修改 [root@nova-92 logs]# find /var/lib/docker/ -na ...

  4. 求你了,别再说Java对象都是在堆内存上分配空间的了!

    Java作为一种面向对象的,跨平台语言,其对象.内存等一直是比较难的知识点,所以,即使是一个Java的初学者,也一定或多或少的对JVM有一些了解.可以说,关于JVM的相关知识,基本是每个Java开发者 ...

  5. 栈 堆 stack heap 堆内存 栈内存 内存分配中的堆和栈 掌握堆内存的权柄就是返回的指针 栈是面向线程的而堆是面向进程的。 new/delete and malloc/ free 指针与内存模型

    小结: 1.栈内存 为什么快? Due to this nature, the process of storing and retrieving data from the stack is ver ...

  6. JVM知识(一) 求你了,别再说Java对象都是在堆内存上分配空间的了!

    求你了,别再说Java对象都是在堆内存上分配空间的了! https://baijiahao.baidu.com/s?id=1661296872935371634&wfr=spider& ...

  7. Java虚拟机的内存组成以及堆内存介绍

    一.java内存组成介绍:堆(Heap)和非堆(Non-heap)内存 按照官方的说法:“Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配.堆是在 Java 虚拟机启 ...

  8. 浅析JAVA中堆内存与栈内存的区别

    Java把内存划分成两种:一种是栈内存,一种是堆内存. 一.栈内存 存放基本类型的变量,对象的引用和方法调用,遵循先入后出的原则.     栈内存在函数中定义的“一些基本类型的变量和对象的引用变量”都 ...

  9. Java堆内存的十个要点

    Java中的堆空间是什么? 当Java程序开始运行时,JVM会从操作系统获取一些内存.JVM使用这些内存,这些内存的一部分就是堆内存.堆内存通常在存储地址的底层,向上排列.当一个对象通过new关键字或 ...

随机推荐

  1. 安装APK时报 Installation failed with message Failed to finalize session : INSTALL_FAILED_USER_RESTRICTED: Invalid apk.

    Installation failed with message Failed to finalize session : INSTALL_FAILED_USER_RESTRICTED: Invali ...

  2. user agent stylesheet -- 浏览器默认样式

    user agent stylesheet 从字面意义上很容易理解他表示用户浏览器的样式表. 今天在做项目时,无意间发现一个元素我并没有设置li的text-align:center : 但其中的img ...

  3. PL/SQL 游标

    本随笔不是原创,只是学习笔记,用于加深记忆,原创地址PL/SQL --> 游标 一.游标的相关概念和特性 1.定义: 映射到结果集中的某一行的特定位置,类似与C语言中的指针.即通过游标方式定位到 ...

  4. PHP多维数据排序(不区分大小字母)

    1. PHP中最普通的数组排序方法 sort(); 看个例子: <?php $test = array(); $test[] = 'ABCD'; $test[] = 'aaaa'; $test[ ...

  5. 入门系列之在Ubuntu上使用MySQL设置远程数据库优化站点性能

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由苏子晨 发表于云+社区专栏 介绍 随着您的应用程序或网站的增长,您可能已经超出了当前的服务器设置.如果您在同一台计算机上托管Web服务 ...

  6. 比较2个文件内容不同行的shell脚本

    第一种:grep命令法 命令如下:grep -vxFf file1 file2 > a.txt 其中file2是大文件,file1是小文件 第一种:comm命令法 命令如下:comm  file ...

  7. HttpContext在多线程异步调用中的使用方案

    1.在线程调用中,有时候会碰到操作文件之类的功能.对于开发人员来说,他们并不知道网站会被部署在服务器的那个角落里面,因此根本无法确定真实的物理路径(当然可以使用配置文件来配置物理路径),他们唯一知道的 ...

  8. Java中的断言 Assert

    今天正好遇到了,就记一下 一.作用: 用与编写单元测试 二.assert 关键字 assert 理论上和 if类似, 但是assert 仅仅用于测试, 不能用于业务 如果发现断言无效, 则可能时ide ...

  9. Maven打包时,不包含jar包

    在给Maven项目打war包时,如果不想把依赖中的jar包也包含进去,可以在plugins中加入 <span style="white-space:pre"> < ...

  10. thinkphp session设置

    <?php namespace Home\Controller; use think\Controller; /*登录*/ class LoginController extends Publi ...