调优好多次,次次都达不到理想状态,这次有不一样的收获,记录一下,以示庆祝!

调优分两个大致的方向吧,一个是对 ELK 集群进行调优,其中包括 ES 的性能调优,Logstash 数据读入时调用 bulk API 时的一些参数调优。另一方面,对数据本身的 mappings,field 做调优,远比想象中效率要提高很多。

应用场景

KFK -> Logstash -> ES

官方建议

本文主要参考官方性能调优,Tune for indexing speedTune for disk usage。实验环境中部署的是5.5.2,但是基本各版本的调优策略没有大的变动。我主要需要做的是 index 的调优,所以对 search 性能上有所取舍和牺牲也很正常。

常规的如下,官方链接说的很清晰了,本文不细讲。

  1. Use bulk requests
  2. Use multiple workers/threads to send data to Elasticsearch
  3. Increase the refresh interval
  4. Disable refresh and replicas for initial loads
  5. Disable swapping
  6. Give memory to the filesystem cache
  7. Use auto-generated ids
  8. Use faster hardware
  9. Indexing buffer size
  10. Additional optimizations
  • Disable the features you do not need
  • Don’t use default dynamic string mappings
  • Disable _all
  • Use best_compression
  • Use the smallest numeric type that is sufficient

详细说一下,调优过程中特别有感触的几条。

Auto generated id 可以省很多时间

让 ID 自增加,而不是生成 ID 再塞进 ES 集群,可以不用增加 ES 查询 ID 唯一性的负担。当然这个地方也是一个取舍,如果你的业务对于唯一性要求很高,同时对于 index 的时间性能上要求不高,那么这条索引策略就不是必需的了。

Disable _all 不只是省空间而已

在模版内把所有字段的 _all 都 disable 之后,明显速度提升 30%。考虑到字段越多,这个 disable _all 的效果应该越明显。

curl -XPUT http://ES_URL:9200/ES_INDEX/ -d '
{
  "mappings": {
    "ES_TYPE": {
      "_all": {
        "enabled": false   
      }
    }
  }
}'

或者用 template 设置:

"mappings": {
  "_default_": {
    ...
    "_all": {
      "norms": false,
      "enabled": false
    },
    ...
  }
}

如图:

flink写入es 的java flink写入es调优_调优

影响 Logstash Bulk API Indexing 速度的因素

名称

字段

输入/输出

默认值

Flush size

flush_size

Output


Flush interval

idle_flush_time

Output

默认1s

Batch size -b

pipeline.batch.size

Input

默认125

Worker num -w

pipeline.workers

Input

默认CPU cores

输出到es

pipeline.output.workers

Output

默认1

其中 pipeline.workers * batch_size / flush_size = Logstash 调用 Bulk API 的次数。 flush_size 和 batch_size 和 LS_HEAP_SIZE 是有关系的,并且单次 batch_size 官方建议维持在 10-15M 之间,超过 20M 的多个 document,会被拆分;超过 20M 的单个 document 将被独立 output 到 ES。

想要知道到底怎样的 batch_size 和 flush_size 合适,官方给出的建议是,依次等量递增的尝试。一般来说,flush_size 不宜超过 pipeline.workers * batch_size 的大小,太大对调优没有作用。
pipeline.output.workers 这个参数调优的时候,基本没啥特别贡献,改日阅读源码再来参详。

其实无非两种方式,在 logstash 工作的时候,他会等 flush_size 满了,output 给 ES。那么如果这个 pool 一直不满,那么他就会等到 flush_interval 期满,把未满的 pool 中的数据,output 给 ES。

其他

调高 refresh interval

默认 1s,如果业务上对实时性要求没有那么高的话,可以调整至 30s。refresh interval 是为了数据可被搜索到。

index.refresh_interval: 30s

调高 translog interval

translog interval 是为了保证数据已经成功落盘。

index.translog.sync_interval: 30s
index.translog.durability: async

Logstash 去除无用字段

# in Logstash instance conf
filter {
  mutate {    
    remove_field => "message"
  }
}

pipeline.workers 和 consumer_threads 区别

# in Logstash instance conf
input {  
  kafka {  
    bootstrap_servers => "KFK_SERVERS"
    topics => ["TOPIC"]
    auto_offset_reset => "latest"
    group_id => "GROUP_ID"
    consumer_threads => 1
    codec => "json"
  }
}

事实上 workers 是进程,consumer_threads 是线程,所以建议在本身硬件条件有限制的时候,使用线程。因为无论是进程还是线程,一个 KFK partition 只能对应一个消费者。一个消费者可以消费多个 KFK partition 中的数据。