elasticsearch5.3.0 bulk index 效能調優實踐
導語: 騰訊雲CDN上每天產生大量回源日誌,回源日誌通常用在問題定位的時候比較有用。這裡使用filebeat+logstash+elasticsearch的方案收集、儲存日誌資料並提供查詢。當前的使用場景裡,每天有70億條日誌需要儲存,屬於寫多讀少的場景。本文整理了在搭建elasticsearch叢集的時候需要注意的配置項,通過對這些配置項的調整,期望提高elasticsearch寫入的效能。
一、叢集基本資訊
1. 每天日誌量70億
2. ES版本: 5.3.0
3. 機器部署
- master node: 3臺
- data node: TS60*10
- client node: 2臺
二、 寫入優化措施及說明
未進行配置優化之前,ES叢集負載非常高,主要表現在磁碟IO上,寫入的qps在2萬/s左右
為了提高寫入的效能,筆者蒐集了官方文件以及一些資料,有如下優化措施。
- 優化點: 減少重新整理頻率,降低潛在的寫磁碟效能損耗
- 官網解釋: How often to perform a refresh operation, which makes recent changes to the index visible to search. Defaults to 1s. Can be set to -1 to disable refresh.
-
優化點: 減少寫磁碟的頻率
python { "index"
-
Lucene只有在commit的時候才會把之前的變更持久化儲存到磁碟(每次操作都寫到磁碟的話,代價太大),在commit之前如果出現故障,上一次commit之後的變更都會丟失
-
為了防止資料丟失,Lucene會把變更操作都記錄在translog裡,在出現故障的時候,從上次commit起記錄在translog裡的變更都可以恢復,儘量保證資料不丟失
-
Lucene的flush操作就是執行一次commit,同時開始記錄一個新的translog,所以translog是用來記錄從上次commit到下一次commit之間的操作的
-
flush操作的頻率是通過translog的大小控制的,當translog大小達到一定值的時候就執行一次flush,對應引數為index.translog.flush_threshold_size,預設值是512mb,這裡調整為1gb,減少flush的次數
-
translog本身是檔案,也需要儲存到磁碟,它的儲存方式通過index.translog.durability和index.translog.sync_interval設定。預設情況下,index.translog.durability=request,意為每次請求都會把translog寫到磁碟。這種設定可以降低資料丟失的風險,但是磁碟IO開銷會較大
-
這裡採用非同步方式持久化translog,每隔30秒寫一次磁碟
3. index.store.throttle.type: "none"
-
1.4的文件關於這個引數的解釋:
index操作首先會生成很多小的segment,會有非同步邏輯合併(merge)這些segment
merge操作比較消耗IO,當系統IO效能比較差的時候,merge會影響查詢和索引的效能。
index.store.throttle.type和index.store.throttle.max_bytes_per_sec可以在節點級或者index級限制merge操作消耗的磁碟頻寬,防止因為merge導致磁碟高負載,影響其他操作 -
另一篇關於ES2.x index調優的文章裡講到,如果不關心查詢的效能,可以把index.store.throttle.type設為none,意為不對merge操作限速
這個引數預設配置是針對merge操作限制使用磁碟頻寬20MBps
-
優化點: 減少併發併發merge對磁碟的消耗
-
index由多個shard組成,每個shard又分成很多segment,segment是index資料儲存的最小單位
-
segment比較多的時候會影響搜尋效能(要查詢很多segment),ES有離線的邏輯對小的segment進行合併,優化查詢效能。但是合併過程中會消耗較多磁碟IO,會影響查詢效能
-
index.merge.scheduler.max_thread_count控制併發的merge執行緒數,如果儲存是併發效能較好的SSD,可以用系統預設的max(1, min(4, availableProcessors / 2)),普通磁碟的話設為1
-
優化點: 降低被動寫磁碟的可能性
-
該配置項指定了用於索引操作的記憶體大小,索引的結果先存在記憶體中,快取空間滿了的話,快取的內容會以segment為單位寫到磁碟。顯然,增大快取空間大小可以降低被動寫磁碟的頻率
三、 優化思路梳理
1. 目標: 優化index效能
2. 主要降低index效能的因素: 磁碟IO(基於觀察,負載非常高)
3. 哪些操作在消耗磁碟IO
- index refresh(不確定有沒有寫磁碟,待確認)
- Lucene flush
- translog persistant
- index buffer不足導致被動寫磁碟
- segment merge
關於segment merge有兩個調整,(1)減少併發merge的執行緒數,(2)放開merge的磁碟頻寬限制。這裡猜測是因為,merge操作是要做的,但是併發的merge比較耗磁碟IO,折中的方案是減少併發,加強單執行緒merge
四、 測試
以上配置全部用上之後,叢集負載瞬間降低了,但是不清楚是哪個配置,或者哪些配置的影響比較大,下面通過測試確認了這些配置的影響
1. 測試方法
使用現網流量進行測試
將上述全部優化項啟用的時候作為基準,分別禁用單個優化項,觀察ES寫入效能和叢集負載
2. 測試日期:20170923
3. 測試資料
對比組 | 時間 | qps | 負載 | 說明 |
---|---|---|---|---|
基準 | 14:30~15:00 | 61685 | 3 | - |
併發merge執行緒數設為預設(15:09) | 15:30~16:00 | 64831 | 3 | 剛修改配置qps有個小凸尖,隨後平穩 |
禁用translog優化(16:07) | 16:12~16:22 | 18399 | 39 | qps暴跌,負載猛增 |
refresh interval使用預設值1s(16:28) | 16:31~17:01 | 57012 | 5 | qps比基準微降,負載微曾 |
開啟merge限流(17:05) | 17:10~17:20 | 61862 | 2.5 | 和基準持平 |
4. 壓測
按照所有優化項開啟的設定,使用python api開啟多執行緒向ES叢集發起bulk index請求,同時觀察kibana monitor介面,發現index qps達到30w/s,隨後叢集很快掛掉。
五、結論
以上測試可以看到
- translog優化禁用的時候叢集負載最高,寫入效能最差
- index refresh操作對寫入的效能略有影響
- segment merge對寫入效能影響非常小
附錄
1. ES儲存節點完整配置
cluster.routing.allocation.enable: all
bootstrap.system_call_filter: false
discovery.zen.ping.unicast.hosts: ["host0", "host1", "host2"]
thread_pool.bulk.queue_size: 6000
network.host: ${lanip}
cluster.routing.allocation.node_concurrent_recoveries: 128
path.data:
- /data1/cdn_log/data
- /data2/cdn_log/data
- /data3/cdn_log/data
- /data4/cdn_log/data
- /data5/cdn_log/data
- /data6/cdn_log/data
- /data7/cdn_log/data
- /data8/cdn_log/data
- /data9/cdn_log/data
- /data10/cdn_log/data
- /data11/cdn_log/data
- /data12/cdn_log/data
node.master: false
path.logs: /data/log/hy-es
discovery.zen.minimum_master_nodes: 2
bootstrap.memory_lock: false
node.data: true
#node.attr.rack: r1
http.port: 9200
gateway.recover_after_data_nodes: 7
node.name: node-5
gateway.recover_after_master_nodes: 2
cluster.name: your_cluster_name
xpack.security.enabled: false
action.destructive_requires_name: true
indices.recovery.max_bytes_per_sec: 200mb
indices.memory.index_buffer_size: 20%
2. index template配置
{
"order": 0,
"template": "hy-log-*",
"settings": {
"index": {
"refresh_interval": "30s",
"number_of_shards": "20",
"translog": {
"flush_threshold_size": "1gb",
"sync_interval": "30s",
"durability": "async"
},
"number_of_replicas": "0"
}
},
"mappings": {
"_default_": {
"dynamic_templates": [
{
"strings_as_keywords": {
"mapping": {
"index": "not_analyzed"
},
"match_mapping_type": "string"
}
}
]
}
},
"aliases": {}
}