ElasticSearch 调优----陆续更新

本文提供了一系列Elasticsearch性能优化策略,涵盖堆内存调整、禁用内存交换、增加文件句柄限制、优化线程配置、调整分片与副本设置等关键参数。深入探讨了系统配置、索引管理及集群规划的最佳实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

1、增大es堆内存

 不设置时默认为1G,但不适合生产环境,可在启动时设置,如下

ES_JAVA_OPTS="-Xms26g -Xmx26g" ./bin/elasticsearch -d

确保最小和最大值相同,大小通常为系统内存的一半;当系统内存很大时,最大设置为26G(不要超过)即可。

可参考:https://www.elastic.co/guide/en/elasticsearch/reference/5.2/heap-size.html

2、禁用内存swap提高性能

内存交换 对服务器性能来说是严重的。比如在内存交换到磁盘上,一个 100 微秒的操作可能变成 10 毫秒。 再想想那么多 10 微秒的操作时延累加起来后对性能有多大影响。 

 修改配置文件:conf/elasticsearch.yml,增加如下项:

bootstrap.memory_lock: true

可参考:https://www.elastic.co/guide/en/elasticsearch/reference/5.2/setup-configuration-memory.html

3、增加用户能打开的最多文件数

默认设置会很小,尝试增大这个限制

修改文件:vi /etc/security/limits.conf 添加下面两项:

* soft nofile 65536

* hard nofile 131072

可参考:https://www.elastic.co/guide/en/elasticsearch/reference/5.2/setting-system-settings.html

4、虚拟内存

 Elasticsearch 对各种文件混合使用了 NioFs( 注:非阻塞文件系统)和 MMapFs ( 注:内存映射文件系统)。系统默认的对mmap的限制有点低,可以通过设置 sudo vim /etc/sysctl.conf:

vm.max_map_count=262144

然后执行:sysctl -p

可参考:https://www.elastic.co/guide/en/elasticsearch/reference/5.2/vm-max-map-count.html

5、优化线程数

确保ES能使用的线程数大于2048,可通过ulimit -u 查看线程数,若小于2048则可设置sudo vim /etc/security/limits.conf:

*  soft nproc 65535

*  hard nproc 65535

可参考:https://www.elastic.co/guide/en/elasticsearch/reference/5.2/max-number-of-threads.html

6、防止master节点"split brain"

设置配置文件,conf/elasticsearch.yml

discovery.zen.minimum_master_nodes: N

 

# N =(适合选为master的节点数 / 2) + 1

# 适合选为master的节点数 通过即为 ES的节点数

可参考:https://www.elastic.co/guide/en/elasticsearch/reference/5.2/important-settings.html#minimum_master_nodes

7、Elasticsearch分片数与分片大小

分片数:设置分片数量需预估未来索引的增长,这里建议设置为节点数的N倍(具体数值要结合分片大小判断)

分片大小:单个分片建议不超过30G,超出过多会影响性能

分片数计算公式:分片数 = N * 数据节点数,其中 N >=1

如:假设目前需要建一个以天为周期的日期索引,有10个数据节点,预计该索引一天的数据量为1TB,则每个节点的可分配:1024G / 10 = 102.4G,N可以设置为102.4G / 30G  + 1 = 4,即设置10 * 4 = 40个分片

8、ElasticSearch副本数

具体看业务场景,若是对数据安全特别敏感的业务建议设置为3,而希望得到最好的性能且允许数据丢失的场景,可以设置为0,一般建议设置为1

9、集群规划

  • 独立的master节点,不存储数据, 数量不少于2
  • 数据节点(Data Node)
  • 查询节点(Query Node),起到负载均衡的作用

10、replica数目

为了让创建的es index在每台datanode上均匀分布,同一个datanode上同一个index的shard数目不应超过3个。

计算公式: (number_of_shard * (1+number_of_replicas)) < 3*number_of_datanodes

每台机器上分配的shard数目

"index.routing.allocation.total_shards_per_node": "2",

11、refresh时间间隔

默认的刷新时间间隔是1s,对于写入量很大的场景,这样的配置会导致写入吞吐量很低,适当提高刷新间隔,可以提升写入量,代价就是让新写入的数据在60s之后可以被搜索,新数据可见的及时性有所下降。

"index.refresh_interval": "60s"
 

12、translog

降低数据flush到磁盘的频率。如果对数据丢失有一定的容忍,可以打开async模式。

"index.translog.flush_threshold_ops": "1000000",
"index.translog.durability": "async",

13、merge相关参数

"index.merge.policy.floor_segment": "100mb",
"index.merge.scheduler.max_thread_count": "1",
"index.merge.policy.min_merge_size": "10mb"

14、mapping设置

对于不参与搜索的字段(fields), 将其index方法设置为no, 如果对分词没有需求,对参与搜索的字段,其index方法设置为not_analyzed 多使用dynamic_template

15、集群参数调优

避免shard的频繁rebalance,将allocation的类型设置为new_primaries, 将默认并行rebalance由2设置为更大的一些的值

避免每次更新mapping, 针对2.x以下的版本

"indices.cluster.send_refresh_mapping": false
调整threadpool, size不要超过core数目,否则线程之间的context switching会消耗掉大量的cpu时间,导致load过高。 如果没有把握,那就不要去调整。

16、定期清理cache

为避免fields data占用大量的jvm内存,可以通过定期清理的方式来释放缓存的数据。释放的内容包括field data, filter cache, query cache

curl -XPOST "localhost:9200/_cache/clear"

17、归并线程配置

segment 归并的过程,需要先读取 segment,归并计算,再写一遍 segment,最后还要保证刷到磁盘。可以说,这是一个非常消耗磁盘 IO 和 CPU 的任务。所以,ES 提供了对归并线程的限速机制,确保这个任务不会过分影响到其他任务。

在 5.0 之前,归并线程的限速配置 indices.store.throttle.max_bytes_per_sec 是 20MB。对于写入量较大,磁盘转速较高,甚至使用 SSD 盘的服务器来说,这个限速是明显过低的。对于 Elastic Stack 应用,社区广泛的建议是可以适当调大到 100MB或者更高。

# curl -XPUT http://127.0.0.1:9200/_cluster/settings -d'
{
"persistent" : {
"indices.store.throttle.max_bytes_per_sec" : "100mb"
}
}'
5.0 开始,ES 对此作了大幅度改进,使用了 Lucene 的 CMS(ConcurrentMergeScheduler) 的 auto throttle 机制,正常情况下已经不再需要手动配置 indices.store.throttle.max_bytes_per_sec 了。官方文档中都已经删除了相关介绍,不过从源码中还是可以看到,这个值目前的默认设置是 10240 MB。

归并线程的数目,ES 也是有所控制的。默认数目的计算公式是: Math.min(3, Runtime.getRuntime().availableProcessors() / 2)。即服务器 CPU 核数的一半大于 3 时,启动 3 个归并线程;否则启动跟 CPU 核数的一半相等的线程数。相信一般做 Elastic Stack 的服务器 CPU 合数都会在 6 个以上。所以一般来说就是 3 个归并线程。如果你确定自己磁盘性能跟不上,可以降低index.merge.scheduler.max_thread_count 配置,免得 IO 情况更加恶化。

1、归并策略
归并线程是按照一定的运行策略来挑选 segment 进行归并的。主要有以下几条:

index.merge.policy.floor_segment 默认 2MB,小于这个大小的 segment,优先被归并。
index.merge.policy.max_merge_at_once 默认一次最多归并 10 个 segment
index.merge.policy.max_merge_at_once_explicit 默认 forcemerge 时一次最多归并 30 个 segment。
index.merge.policy.max_merged_segment 默认 5 GB,大于这个大小的 segment,不用参与归并。forcemerge 除外。
根据这段策略,其实我们也可以从另一个角度考虑如何减少 segment 归并的消耗以及提高响应的办法:加大 flush 间隔,尽量让每次新生成的 segment 本身大小就比较大。

2、forcemerge 接口
既然默认的最大 segment 大小是 5GB。那么一个比较庞大的数据索引,就必然会有为数不少的 segment 永远存在,这对文件句柄,内存等资源都是极大的浪费。但是由于归并任务太消耗资源,所以一般不太选择加大 index.merge.policy.max_merged_segment 配置,而是在负载较低的时间段,通过 forcemerge 接口,强制归并 segment。

# curl -XPOST http://127.0.0.1:9200/logstash-2015-06.10/_forcemerge?max_num_segments=1
由于 forcemerge 线程对资源的消耗比普通的归并线程大得多,所以,绝对不建议对还在写入数据的热索引执行这个操作。这个问题对于 Elastic Stack 来说非常好办,一般索引都是按天分割的。更合适的任务定义方式

3、其它
marvel: 安装marvel插件,多观察系统资源占用情况,包括内存,cpu
日志: 对es的运行日志要经常查看,检查index配置是否合理,以及入库数据是否存在异常

18、重新分配分片

elasticsearch可以通过reroute api来手动进行索引分片的分配。

不过要想完全手动,必须先把cluster.routing.allocation.disable_allocation参数设置为true,禁止es进行自动索引分片分配,否则你从一节点把分片移到另外一个节点,那么另外一个节点的一个分片又会移到那个节点。数据量很少的时候,可能影响不大,但是如果数据量很大,这个参数必须要设置,因为如果不设置,即便你不手动迁移分片,在我们重启机群的时候,也会产生分片的迁移,导致大量资源被占用,重启变慢.

一共有三种操作,分别为:移动(move),取消(cancel)和分配(allocate)。下面分别介绍这三种情况:

移动(move)

把分片从一节点移动到另一个节点。可以指定索引名和分片号。

取消(cancel)

取消分配一个分片。可以指定索引名和分片号。node参数可以指定在那个节点取消正在分配的分片。allow_primary参数支持取消分配主分片。

分配(allocate)

分配一个未分配的分片到指定节点。可以指定索引名和分片号。node参数指定分配到那个节点。allow_primary参数可以强制分配主分片,不过这样可能导致数据丢失。我一般用来清空某个未分配分片的数据的时候才设置这个参数

集群索引中可能由多个分片构成,并且每个分片可以拥有多个副本,将一个单独的索引分为多个分片,可以处理不能在单一服务器上运行的
大型索引.
由于每个分片有多个副本,通过副本分配到多个服务器,可以提高查询的负载能力.
为了进行分片和副本操作,需要确定将这些分片和副本放到集群节点的哪个位置,需要确定把每个分片和副本分配到哪台服务器/节点上.

1.索引创建&指定节点参数:
$curl -XPOST 'http://localhost:9200/filebeate-ali-hk-fd-tss1'
$curl -XPUT 'http://localhost:9200/filebeat-ali-hk-fd-tss1/_settings' -d '{
"index.routing.allocation.include.zone":"ali-hk-ops-elk1"
}'
将索引指定存放在elk1的节点上

$curl -XPUT 'http://localhost:9200/filebeat-ali-hk-fd-tss1/settings' -d '{
"index.routing.allocation.include._ip":"ip_addr1,ip_addr2"
}'
根据ip地址指定索引的分配节点

2.排除索引分配的节点:
$curl -XPOST 'http://localhost:9200/filebeat-ali-hk-fd-tss2'
$curl -XPUT 'http://localhost:9200/filebeat-ali-hk-fd-tss2/_setting' -d '{
"index.routing.allocation.exclude.zone":"ali-hk-ops-elk2"
}'

$curl -XPUT 'http://localhost:9200/filebeat-ali-hk-fd-tss2/_setting' -d '{
"index.routing.allocation.exclude._ip":"ip_addr1,ip_addr2"
}'
根据ip地址排除索引分配的节点

3.每个节点上分片和副本数量的控制:
对一个索引指定每个节点上的最大分片数量:
$curl -XPUT 'http://localhost:9200/filebeat-ali-hk-fd-tss1/_settings' -d '{
"index.routing.allocation.total_shards_per_node":1
}'

如果配置不当,导致主分片无法分配的话,集群就会处于red状态.

4.手动移动分片和副本:
移动分片:
$curl -XPOST 'http://localhost:9200/_cluster/reroute' -d '{
"commands":[{
"move":{
"index":"filebeat-ali-hk-fd-tss1",
"shard":1,
"from_node":"ali-hk-ops-elk1",
"to_node":"ali-hk-ops-elk2"
}
}]
}'

取消分片:
$curl -XPOST 'http://localhost:9200/_cluster/reroute' -d '{
"commands":[{
"cancel":{
"index":"filebeat-ali-hk-fd-tss1",
"shard":1,
"node":"ali-hk-ops-elk1"
}
}]
}'

分配分片(用来分配未分配状态的分片,会导致数据丢失):
$curl -XPOST 'http://localhost:9200/_cluster/reroute' -d '{
"commands":[{
"allocate":{
"index":"filebeat-ali-hk-fd-tss1",
"shard":1,
"node":"ali-hk-ops-elk1",

allow_primary" : true   (允许该分片做主分片)

 

}
}]
}'

将某个未分配的索引手动分配到某个节点上.

$curl -XPOST 'http://localhost:9200/_cluster/reroute' -d '{
"commands":[
{
"move":{
"index":"filebeat-ali-hk-fd-tss1",
"shard":1,
"from_node":"ali-hk-ops-elk1",
"to_node":"ali-hk-ops-elk2"
}
},
{
"cancel":{
"index":"filebeat-ali-hk-fd-tss1",
"shard":1,
"node":"ali-hk-ops-elk1"
}
},
{
"allocate":{
"index":"filebeat-ali-hk-fd-tss1",
"shard":1,
"node":"ali-hk-ops-elk1"
}
}]
}'

5.关于unassigned shards的问题解决:

1)出现大量的unassigned shards
2)集群的状态为:red


集群状态:red-->存在不可用的主分片

A:fix unassigned shards:
查看所有分片的状态:
$curl -XGET 'http://localhost:9200/_cat/shards'
查询所有unassigned的分片:
$curl -XGET 'http://localhost:9200/_cat/shards' | grep UNASSIGNED

B:查询得到master节点的唯一标识:
$curl -XGET 'http://localhost:9200/_nodes/process?pretty=true'

C:执行route对unassigned的索引进行手动分片:
for index in $(curl -XGET 'http://localhost:9200/_cat/shards' | grep UNASSIGNED |awk '{print 1}'|sort |uniq):do for shards in1}'|sort |uniq):do for shards in(curl -XGET 'http://localhost:9200/_cat/shards' | grep UNASSIGNED | grep index | awk '{printindex | awk '{print2}'|sort|uniq):do
curl XPOST 'http://localhost:9200/_cluster/reroute'-d '{
"commands":[
{
"allocate":{
"index":index,"shards":index,"shards":shards,
"node":"ali-k-ops-elk1",
"allow_primary":"true"
}
}
]
}'

19、集群升级操作

#1、  关闭自动分片
PUT  _cluster/settings
{
    "persistent":  {
                "cluster":  {
                        "routing":  {
                                "rebalance":  {
                                        "enable":  "none"
                                },
                                "allocation":  {
                                        "enable":  "none"
                                }
                        }
                }
        }
}


#2、  备份老配置cp  elasticsearch.yml  elasticsearch.yml_20181017  然后在每个节点增加如下配置到elasticsearch.yml,去除历史相同配置
#3、  更新后的节点依次重启操作:确保前一个节点启动正常,并且状态正常后再重启下一个节点

通过es_head插件关闭索引,停止ES集群
#    重启整个集群:顺序是先启master组(所有的master重启完成后要停止集群的shard自动均衡),再启hot组节点,最后启stale组节点
  relo、init、unassign这3项都变成0
#4、  集群正常后,开启自动分片
PUT  _cluster/settings
{
    "persistent":  {
                "cluster":  {
                        "routing":  {
                                "rebalance":  {
                                        "enable":  "all"
                                },
                                "allocation":  {
                                        "enable":  "all"
                                }
                        }
                }
        }
}


#  memory_lock
bootstrap.memory_lock:  true

#  cache  
indices.cache.cleanup_interval:  5m
indices.memory.index_buffer_size:  20%
indices.queries.cache.count:  100000
indices.queries.cache.size:  10%
indices.requests.cache.size:  10%
indices.requests.cache.expire:  5m
indices.store.throttle.type:  none

#  search
search.highlight.term_vector_multi_value:  false

#  thread_pool
thread_pool.bulk.size:  20
thread_pool.search.size:  25
thread_pool.bulk.queue_size:  1024
thread_pool.force_merge.size:  4

#  fielddata
indices.fielddata.cache.size:  40%

磁盘性能测试:
1、先熟悉两个特殊的设备:
        (1)/dev/null:回收站、无底洞。
        (2)/dev/zero:产生字符。

2、测试磁盘写能力
        time  dd  if=/dev/zero  of=/cy/testw.dbf  bs=4k  count=10000
real  0m36.669s
        写速度为:4*10000/1024/36.669=M/s。
rm  -f  /cy/testw.dbf

3、测试磁盘读能力
        time  dd  if=/dev/sdb  of=/dev/null  bs=4k
        

4、测试同时读写能力
        time  dd  if=/dev/sdb  of=/cy/testrw.dbf  bs=4k
rm  -f  /cy/testrw.dbf

系统参数调优:
sysctl  -w  vm.dirty_ratio=20
sysctl  -w  vm.dirty_background_ratio=10

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值