調優好多次,次次都達不到理想狀態,這次有不一樣的收穫,記錄一下,以示慶祝!
調優分兩個大致的方向吧,一個是對 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 中的數據。