menu Spark社区 | 一条苦行狗的家
search
close
Elasticsearch参数优化
672 浏览 | 0 评论

Elasticsearch参数优化

(1)

解决es启动的警告信息【es中Too many open files的问题】

vi /etc/security/limits.conf
# 添加下面两行
* soft nofile 65536
* hard nofile 131072

修改配置文件调整ES的JVM内存大小

  1. 修改bin/elasticsearch.in.sh中的ES_MIN_MEM和ES_MAX_MEM的大小,建议设置一样大,避免频繁的分配内存,根据服务器内存大小,一般分配60%左右(默认256M)
  2. 内存最大不要超过32G

查看官网

Don’t Cross 32 GB! 

There is another reason to not allocate enormous heaps to Elasticsearch. As it turns out, the HotSpot JVM uses a trick to compress object pointers when heaps are less than around 32 GB.

In Java, all objects are allocated on the heap and referenced by a pointer. Ordinary object pointers (OOP) point at these objects, and are traditionally the size of the CPU’s native word: either 32 bits or 64 bits, depending on the processor. The pointer references the exact byte location of the value.

For 32-bit systems, this means the maximum heap size is 4 GB. For 64-bit systems, the heap size can get much larger, but the overhead of 64-bit pointers means there is more wasted space simply because the pointer is larger. And worse than wasted space, the larger pointers eat up more bandwidth when moving values between main memory and various caches (LLC, L1, and so forth).

Java uses a trick called compressed oops to get around this problem. Instead of pointing at exact byte locations in memory, the pointers reference object offsets. This means a 32-bit pointer can reference four billion objects, rather than four billion bytes. Ultimately, this means the heap can grow to around 32 GB of physical size while still using a 32-bit pointer.

Once you cross that magical ~32 GB boundary, the pointers switch back to ordinary object pointers. The size of each pointer grows, more CPU-memory bandwidth is used, and you effectively lose memory. In fact, it takes until around 40–50 GB of allocated heap before you have the same effective memory of a heap just under 32 GB using compressed oops.

The moral of the story is this: even when you have memory to spare, try to avoid crossing the 32 GB heap boundary. It wastes memory, reduces CPU performance, and makes the GC struggle with large heaps.

### 简陋翻译
不要超过32 GB!

还有另一个原因是不将巨大的堆分配给ElasticSearch。事实证明,当堆小于32GB时,Hotspot JVM使用一种技巧来压缩对象指针。

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

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

Java使用一种叫做压缩OOP的技巧来解决这个问题。指针引用对象偏移量,而不是指向内存中精确的字节位置。这意味着32位指针可以引用40亿个对象,而不是40亿字节。最终,这意味着堆可以增长到32 GB左右的物理大小,同时仍然使用32位指针。

一旦您跨越了32 GB的神奇边界,指针就会切换回普通的对象指针。每个指针的大小都在增加,使用了更多的CPU内存带宽,从而有效地丢失了内存。实际上,在使用压缩OOP获得32 GB以下堆的相同有效内存之前,需要大约40–50 GB的已分配堆。

这个故事的寓意是:即使您有足够的内存,也要尽量避免跨越32GB的堆边界。它浪费内存,降低CPU性能,并使GC难以处理大堆。

设置memory_lock来锁定进程的物理内存地址

  • 避免交换(swapped)来提高性能
  • 修改文件conf/elasticsearch.yml
  • bootstrap.memory_lock:true
  • 需要根据es启动日志修改/etc/security/limits.conf文件(重启系统)

(2)

使用多个分片,可以提升建立索引的能力,5-20个比较合适

  • 如果分片数过少或过多,都会导致检索比较慢
  • 分片数过多会导致检索时打开比较多的文件,另外也会导致多台服务器之间通讯。
  • 而分片过少导致单个分片索引过大,所以检索速度也会慢。
  • 建议单个分片存储20G左右的索引数据【最高也不要超过50G,否则性能会很差】,所以,分片数量=数据总量/20G。

副本多的话,可以提升搜索的能力,但是如果设置很多副本的话,也会对服务器造成额外的压力,因为主分片需要给所有副本同步数据。所以建议最多设置1-2即可。

# 查看某个索引库中每个分片占用的磁盘空间大小
curl -XGET hadoop120:9200/_cat/segments/test?v&h=shard,segment,size

(3)

要定时对索引进行合并优化,不然segment越多,占用的segment memory越多,查询的性能也越差

关于索引合并,参考 es的索引合并

  • 索引量不是很大的话,可以将segment设置为1
  • 在es2.1.0以前调用 _optimize接口,后期改为 _forcemerge接口
  • curl -XPOST hadoop120:9200/test/_forcemerge?max_num_segments=1
  • java代码client.admin().indices().prepareForceMerge("test").setMaxNumSegments(1).get()
  • 索引合并是针对分片的。segment设置为1,则每个分片都有一个索引片段。

针对不使用的index,建议close,减少内存占用。因为只要索引处于open状态,索引库中的segment就会占用内存,close之后就只会占用磁盘空间了。

curl -XPOST hadoop120:9200/test/_close

Deprecated in 2.1.0.
Optimize API has been renamed to the force merge API.
链接:
https://www.elastic.co/guide/en/elasticsearch/reference/2.4/indices-optimize.html


使用cat api 查看segment 的信息【size.memory的单位是字节】
链接:https://www.elastic.co/guide/en/elasticsearch/reference/6.4/cat-segments.html

例子:
查看test索引库中分片,索引片段,占用磁盘空间,占用内存空间:curl -XGET  "localhost:9200/_cat/segments/test?v&h=shard,segment,size,size.memory"
查看所有索引库中分片,索引片段,占用磁盘空间,占用内存空间:curl -XGET  "localhost:9200/_cat/segments?v&h=shard,segment,size,size.memory" 

使用cat api查看索引库的信息
链接:https://www.elastic.co/guide/en/elasticsearch/reference/6.4/cat-indices.html

例子:
查看索引库的状态信息
curl -XGET 'localhost:9200/_cat/indices/test?v'

(4)

  • 删除文档:在es中删除文档,数据不会马上在磁盘上除去,而是在es索引中产生了一个 .del 文件,而在检索过程中这部分数据也会参与检索,es在检索过程会判断是否删除了,如果删除了再过滤掉。这样也会降低检索效率。所以可以执行清除删除文档。

curl -XPOST hadoop120:9200/test/_forcemerge?only_expunge_deletes=true

java代码client.admin().indices().prepareForceMerge("test").setOnlyExpungeDeletes(true).get()

(5)

如果在项目开始的时候需要批量入库大量数据的话,建议将副本数设置为0

  • 因为es在索引数据的时候,如果有副本的存在,数据也会马上同步到副本中,这样会对es增加压力。可以等索引完成后将副本按需要改回来。这样可以提高索引效率。

ES需要注意的问题

  • 在使用java代码操作es集群的时候要保证本地使用的es的版本和集群上es的版本保持一致。
  • 保证集群中的每个节点的JDK版本和es基本配置一致
# es集群中JDK版本不一致可能会导致这个问题:
# org.elasticsearch.transport.RemoteTransportException:Failed to deserialize exception response from stream

# 简陋翻译:
# org.elasticsearch.transport.remotetransportException:未能从流反序列化异常响应

评论

textsms
支持Markdown语法
email
link

mode_comment 全部评论 暂无评论(;´д`)ゞ