1. 程式人生 > >elasticsearch5.3.0 bulk index 效能調優實踐

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"
    : { "translog": { "flush_threshold_size": "1gb", "sync_interval": "30s", "durability": "async" } } }
  • 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": {}
}