全部產品
Search
文件中心

Elasticsearch:通過_split API快速拆分主分區

更新時間:Jun 30, 2024

當您使用Elasticsearch叢集出現索引分區設定不合理(例如索引主分區設定不合理、每個分區存在大量資料等)引發叢集效能問題時,可通過_split API線上擴大主分區數,將現有索引拆分為具有更多主分區的索引。本文介紹如何通過_split API快速拆分主分區。

背景資訊

索引建立後,Elasticsearch不支援修改索引主分區的數量,如果需要修改,一般會使用reindex重建索引,耗時太久。而在6.x版本開始,Elasticsearch支援線上擴大主分區數的Split index API,支援將現有索引拆分為具有更多主分區的索引。

reindex與_split API的效能測試資訊如下:
  • 測試環境:
    • 資料節點:數量為5個,規格為8核16 GB。
    • 索引資料:資料量為183 GB。
    • 分區數:原主分區數為5,目標分區數為20,副本數為0。
  • 測試結果
    方式耗時資源佔用
    reindex2.5小時叢集中有大量的寫QPS,索引所佔節點資源高。
    _split API3分鐘叢集資料節點CPU使用率為78%左右,load_1m為10左右。

前提條件

  • Elasticsearch叢集狀態健康,且負載處於正常水位。
  • 根據叢集資料節點個數、叢集磁碟容量等因素,合理評估索引可拆分的分區數。詳細資料請參見評估Shard
  • 待拆分的索引禁止寫入,且拆分後產生的新索引不存在。
  • Elasticsearch叢集有足夠的磁碟空間儲存拆分後產生的新索引。

操作步驟

  1. 登入目標Elasticsearch執行個體的Kibana控制台,根據頁面提示進入Kibana首頁。
    登入Kibana控制台的具體操作,請參見登入Kibana控制台
    說明 本文以Elasticsearch 7.10.0版本為例,其他版本操作可能略有差別,請以實際介面為準。
  2. 單擊右上方的Dev tools
  3. Console中,執行如下命令,在建立索引時指定index.number_of_routing_shards,設定索引可拆分的分區數。
    以下樣本以7.10版本執行個體為例,在建立dest1索引時指定分區路由數number_of_routing_shards,對主分區進行拆分。可拆分的主分區數需要為number_of_routing_shards的一個因數且為number_of_shards(主分區數)的倍數。如下number_of_shards為2,number_of_routing_shards為24,則可拆分的主分區數支援:4、6、8、12、24。
    說明 使用時需要將dest1替換為您的業務索引名。
    PUT /dest1
    {
      "settings": {
        "index": {
          "number_of_routing_shards": 24,
          "number_of_shards":2
        }
      }
    }
    參數說明
    number_of_routing_shards路由分區數,定義索引可拆分的次數或原始分區可拆分的分區數。建立索引指定該參數,要求索引主分區數必須是路由分區數的一個因數。
    說明
    • Elasticsearch 7.0以下版本,建立索引時必須指定index.number_of_routing_shards,最大值為1024;7.0及以上版本,index.number_of_routing_shards值預設依賴主分區數,如果建立索引時未指定,預設按因子2拆分,並且最多可拆分為1024個分區。例如原索引主分區數為1,則可拆分為1~1024中的任意數;原索引主分區為5,則支援拆分的分區數為:10、20、40、80、160、320以及最大數640(不能超過1024)。
    • 經過shrink後的主分區再進行split時,主分區數為原主分區數的倍數即可。例如原分區數為5,進行split時,支援拆分的分區數為:10、15、20、25、30...,最大不能超過1024。
    number_of_shards索引的主分區數。
  4. 插入資料。
    說明 以下資料僅供測試。
    POST /dest1/_doc/_bulk
    {"index":{}}
    {"productName":"產品A","annual_rate":"3.2200%","describe":"可以自助選擇訊息推送"}
    {"index":{}}
    {"productName":"產品B","annual_rate":"3.1100%","describe":"每天收益到賬訊息推送"}
    {"index":{}}
    {"productName":"產品C","annual_rate":"3.3500%","describe":"每天收益立即到賬訊息推送"}
  5. 禁止對原索引的寫入操作。
    PUT /dest1/_settings
    {
      "settings": {
        "index.blocks.write": true
      }
    }
  6. 拆分原索引並配置新索引,取消新索引的禁止寫入限制。
    POST dest1/_split/dest3
    {
      "settings": {
        "index.number_of_shards": 12,
        "index.blocks.write": null
      }
    }
    以上樣本使用_split API從原索引dest1拆分出新索引dest3,設定新索引的分區數為12,且取消新索引禁止寫限制。
    重要
    • 由於原索引的主分區數為2,index.number_of_routing_shards為24,則拆分後產生的新索引的主分區數需要為原索引主分區數的整數倍且不能超過24,否則Kibana會報錯。
    • split過程會進行segment merge操作,此操作會消耗叢集計算資源,增加叢集負載。因此在操作前需確保叢集有充足的磁碟空間,並建議在業務低峰期操作。
    • 使用時需要將dest1dest3替換為您的業務索引名。
  7. 測試結果。
    通過_cat recovery API查看分區拆分進度,當無拆分分區相關的recovey,且叢集狀態健康,則分區拆分完成。
    • 查看分區拆分進度
      GET _cat/recovery?v&active_only

      當返回結果的index列沒有待拆分的索引時,說明無拆分分區相關的recovey。

    • 查看叢集健康狀態
      GET _cluster/health

      當返回結果中包含"status" : "green"時,說明叢集狀態健康。

常見問題

Q:split完成後,為什麼叢集的CPU使用率、節點load_1m沒有降下來?

A:split過程涉及到對文檔進行重新路由,新索引會存在大量的docs.deleted文檔。通過GET _nodes/hot_threads可看到索引在進行merge操作,所以計算資源負載會比較高,建議在業務低峰期操作。