调优好多次,次次都达不到理想状态,这次有不一样的收获,记录一下,以示庆祝!
调优分两个大致的方向吧,一个是对 ELK 集群进行调优,其中包括 ES 的性能调优,Logstash 数据读入时调用 bulk API 时的一些参数调优。另一方面,对数据本身的 mappings,field 做调优,远比想象中效率要提高很多。
应用场景
KFK -> Logstash -> ES
官方建议
本文主要参考官方性能调优,Tune for indexing speed 及 Tune for disk usage。实验环境中部署的是5.5.2,但是基本各版本的调优策略没有大的变动。我主要需要做的是 index 的调优,所以对 search 性能上有所取舍和牺牲也很正常。
常规的如下,官方链接说的很清晰了,本文不细讲。
- Use bulk requests
- Use multiple workers/threads to send data to Elasticsearch
- Increase the refresh interval
- Disable refresh and replicas for initial loads
- Disable swapping
- Give memory to the filesystem cache
- Use auto-generated ids
- Use faster hardware
- Indexing buffer size
- 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
},
...
}
}
如图:
影响 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 中的数据。