【数据平台】Elasticsearch-调优实践

Elasticsearch调优

本章将叙述elasticsearch的调优,涉及JVM调优、热点线程、水平扩展(分片)、高负载场景调优、高查询场景调优。有关es的安装请参考Elasticsearch搜索引擎一文。

1.1 JVM调优

想必大家都知道,垃圾回收实现目标:需要实现是小而多次的垃圾回收,而不是一次长时间的回收,从而保证应用在稳定的性能水平运行。

1.1.1 使用jstat

命令:jstat -gcutil pid 2000 1000
gcutils:表示监控垃圾回收器的工作;
2000:毫秒表示的采样周期;
1000:是采样的数量;
显示结果:
S0 S1 E O P YGC YGCT FGC FGCT GCT

  • 调优分析(先年轻代,后老年代)
    当S0、S2或者E列显示为100%(或很高时),并且垃圾回收器不能回收这些堆空间,那么,要么是年轻代太小需要增加(如果有充足的剩余物理内存),要么是内存太小问题。
    当O列老年代显示100%(或很高)时,垃圾回收器努力回收它(频繁的垃圾回收),但却不能回收,那么大概意味着没有足够的堆空间。
1.1.2 使用jmap

命令:jmap -dump:file=/opt/heap.dump pid

  • 调优分析
    导入文件后,可以使用gcviewer工具导入进行分析。
1.2 避免内存交换

当物理内存数量不够或者操作系统某些原因认为把一部分RAM内存写入磁盘更好些,就会发生内存交换,如果有部分ES使用内存被写到磁盘然后再从磁盘上读取,这个过程会消耗大量时间和资源。如何下设置保证避免内存交换:

  • 在elasticsearch.yml 中设置boostrap.mlockall属性为true;

  • 设置Xmx和Xms属性值相同,避免JVM改变堆大小,注意内存大小合适,并非越大越好(会导致回收时长变长);

  • 修改/etc/security/limits.conf,添加如下内容(假设运行ES的用户是appuser)
    appuser - nofile 65536
    appuser - memlock unlimited

  • 修改/etc/pam.d/common-session文件,添加如下内容
    session required pam_limits.so

1.3 基准测试

对elasticsearch 指定节点做基准测试,启动命令需要发生变更;

  • 命令:bin/elasticsearch --node.bench true
  • 基准测试
curl -XPUT 'localhost:9200/_bench/?pretty' -d '{
  "name": "firstTest",
  "competitors": [{
    "name": "post_filter",
    "requests": [{
      "post_filter": {
        "term": {
          "link": "hello world"
        }
      }
    }]
  },{
    "name": "filtered",
    "requests": [{
      "query": {
        "filtered": {
          "query": {
            "match_all": {}
          },
          "filter": {
            "term": {
              "link": "hello world"
            }
          }
        }
      }
    }]
  }
  ]
}'

返回数据说明:
name:基准测试名称;
competitors:ES将要执行的测试定义;
num_executor_nodes:在测试期间作为查询源的最大Elasticsearch节点数,默认为1个;
iteration:ES应当为每个竞争者重复执行的次数,默认为5次;
concurrency:每次迭代的并发数,默认5个并发现场;
multiplier:在每一次迭代中每个查询重复的次数,默认重复执行1000次;

  • 查看基准测试进度
curl -XGET 'localhost:9200/_bench?pretty'
  • 中止基准测试
curl -XPOST 'localhost:9200/_bench/abort/firstTest?pretty'
1.4 热点线程检查

假如集群比平时执行缓慢使用了大量的CPU资源,那么可用通过此来进行分析;

  • 热点线程API使用
    查看热点线程API时,通常使用/_nodes/hot_threads查看集群热点线程,或者/_nodes/{node or nodes}/hot_threads查看端点热点线程,例如:
curl ‘localhost:9200/_nodes/host_threads’
每1s周期查看所有节点处于等待状态的热点线程:
curl ‘localhost:9200/_nodes/host_threads?type=wait&interval=1s’
  • 热点线程API响应
0.5% (2.8ms out of 500ms)cpu usage by thread 'elasticsearch[N'Gabtthoth][search][T#10]'
名称:为search的线程,[search]可能会有其他值recovery_stream(回复模块事件)、cache(缓存事件)、merge(索引段合并线程)、index(数据索引线程);
0.5%:统计消耗百分比0.5的CPU时间;
block usage:表示线程处于阻塞状态;
waiting usage:表示线程出游等待状态;

1.5 水平扩展(增加分片)
1.5.1 分片与副本高可用
  • 分片和副本数设置与高可用
    每个分片都必须设置至少1个副本(一般只设置1个副本),一般来说分片数+副本数>=虚拟机节点数,分片和副本ES内部会自动处理其分布到不同节点,如下图所示8个节点由4个分片和1个副本的分布情况。
    分片与副本设置
1.5.2 物理机-虚拟机-节点高可用

现在很多企业的使用虚拟机,都是由物理机分割而成的,有的一台物理机服务器对应多台虚拟机。因此,为了保证Elasticsearch节点数据的高可用,副本和分片最好不应存在于同一台物理机上,最好的分布例如下图所示。
物理机虚拟机与节点高可用
为了实现上面节点分布,需要进行如下配置后,这告诉ES不要把分片和它的副本放在具有相同node.server_name属性的节点上:

对于在第1台物理服务器上的所有es节点来说,在elasticsearch.yml文件中设置如下属性:
node.server_name: server1
cluster.routing.allocation.awareness.attributes: server_name

在其他物理服务器上配置类似。
1.5.3 大规模集群设计节点角色
  • 指派节点角色,ES节点角色有:
    查询聚合节点:分发查询到其他节点,收集和合并结果;
    数据节点:接收数据,存储数据;
    候选主节点:主节点选举;
    默认情况下,Elasticsearch节点兼具查询聚合、数据、候选主节点角色。
  • 查询聚合节点elasticsearch.yml配置
node.master: false
node.data: false
  • 数据节点elasticsearch.yml配置
node.master: false
node.data: true
  • 候选主节点elasticsearch.yml配置
node.master: true
node.data: false
http.enabled: false
通常设置3个候选主节点;
1.6 高负载场景下调优
1.6.1 常规优化建议
– 索引刷新频率

索引刷新频率是指文档需要多长时间文档才能出现在搜索结果中,默认1s。规则:刷新频率越短,查询越慢,且索引文档的吞吐量越低;在查询实时性要求不是特别高场景下,可适当增大刷新频率时间。

# refresh interval API
curl -XPUT "localhost:9200/index_name" -H 'Content-Type: application/json'  -d'{
    "settings": {
        "refresh_interval": "10s"
    }
}'
  • 引申出吞吐量调优
    index.number_of_replicas: 副本数,越小越好,可降低数据同步一致性时间,从而提高写速度;但会影响查询速度;
    index.refresh_interval:刷新频率,越大越好,可降低数据刷新频率,从而提高写速度;但会影响数据查询时效性。

所以针对某些实时性要求不高,夜间批处理场景,可以临时关闭副本数、禁用刷新频率间隔,以提高数据写速度,待任务写完成后再恢复副本数和刷新频率间隔。

#写吞吐量关闭副本和间隔
index.number_of_replicas: "0",
index.refresh_interval: "-1"
–线程池调优

在生产或者压测环境中,ES实例没有100%饱和,但却接收拒绝执行错误,大都因为search 线程设置过小导致程序崩溃, 默认search线程大小=(cpu核数 * 3) / 2 + 1。

Caused by: org.elasticsearch.common.util.concurrent.EsRejectedExecutionException: 
	rejected execution of org.elasticsearch.search.SearchService$3@4d6f25c2 on EsThreadPoolExecutor
	[search, queue capacity = 1000, org.elasticsearch.common.util.concurrent.EsThreadPoolExecutor@24522e89
	[Running, pool size = 13, active threads = 13, queued tasks = 52728, completed tasks = 314227215]]
  • 查看线程状态
curl -XGET 'localhost:9200/_cat/thread_pool/
#也可用此api查询
curl -XGET 'localhost:9200/_cat/thread_pool/search?v&h=id,name,active,queue,rejected,completed'
参数依次:节点名称、线程池名称、线程活动状态、线程队列、线程拒绝
  • 从ElasticSearch5.0 开始,无法通过api更改线程池,需要更改elasticsearch.yml并重启才能生效配置
#允许控制没有线程执行它们的挂起请求队列的初始大小
thread_pool.search.queue_size: 500
#search线程池线程数,默认为核心数乘以5
thread_pool.search.size: 200
#控制queue_size可以调整到的最小数值
thread_pool.search.min_queue_size:10
#控制queue_size可以调整到的最大数值
thread_pool.search.max_queue_size: 1000
#控制在调整队列之前进行测量的操作数。它应该足够大,以便单个操作不会过度偏向计算
thread_pool.search.auto_queue_frame_size: 2000
#控制target_response_time是时间值设置,指示线程池队列中任务目标平均响应耗时;如果任务通常超过此时间,则将调低线程池队列以拒绝任务
thread_pool.search.target_response_time: 6s
–调整段合并过程

原则:如果希望查询更快,就寻求更少的索引段。更少的段会导致更低的RAM消耗、更快的查询速度、更慢的索引速度;更多的段会导致更高的RAM消耗,更慢的查询速度和更快的索引速度。

#elasticsearch.yml 配置
index.merge.policy.merge_factory=8  #默认值10,低于10段更少,高于10段更多
indices.store.throttle.max_bytes_per_sec=150MB  #合并限流,默认20MB/s,对于SSD硬盘可提高到5-10倍
–合理数据(分片与副本)分布

合理数据分片和副本分布,可有效保障ES节点性能和稳定性,应确保每个节点的负载均衡,如下图所示:
好的分片和副本实践

1.6.2 高查询频率场景优化

建议:总是要考虑优化查询结构过滤器的使用等,可参考Elasticsearch 6.x

  • 节点查询缓存(详解)
    有助于查询性能的提升;
--内存限制通过参数indices.queries.cache.size:
indices.queries.cache.size=10% 属性控制缓存的大小,表示给定节点上能够被过利器缓存使用JVM堆内存数量,默认10%,
如果监控缓存逐出比较多,应该考虑增加缓存的大小。

--条数则是通过参数indices.queries.cache.count:
indices.queries.cache.count=1000

--控制是否启用查询缓存。接受true(默认)或 false
index.queries.cache.enabled=true
  • 分片请求缓存(详解)
    缓存分片查询的缓存,它的目的是缓存聚合、提示词结果和命中数。如果不使用聚合或提示词,那么使用分片数据缓存毫无意义
 index.requests.cache.enable属性设置为ture,开启索引缓存
curl -XPUT 'localhost:9200/index_name/_settings' -d '}
	" index.requests.cache.enable":true
}'
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Moutai码哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值