使用LogStash將資料同步至PolarSearch

更新時間:
Copy as MD

當您需要將自建ElasticsearchOpenSearch叢集中的資料移轉至PolarSearch時,可以使用LogStash實現資料同步。本文介紹如何配置LogStash,以完成全量資料移轉和持續的增量資料同步兩種情境。

功能簡介

LogStash是一款開源的資料處理管道工具,能夠從多種來源採集資料,經過轉換後,再發送到多種目標儲存。通過為其安裝針對不同資料來源(如Elasticsearch、OpenSearch)和目標(如PolarSearch)的外掛程式,您可以構建一條高效、靈活的資料同步鏈路,以滿足資料移轉或即時同步的需求。

準備工作

在開始操作前,請確保滿足以下環境和許可權要求:

  • 環境依賴:已準備一台可以同時訪問源庫和目標庫網路的伺服器用於運行LogStash。

  • 源庫許可權:用於串連源庫的帳號需具備待同步索引的readread_metadata許可權。

  • 目標庫許可權:用於串連PolarSearch的帳號需具備writecreate_index等資料寫入許可權。

  • 增量同步處理要求:若執行增量同步處理,源索引中必須包含一個時間戳記欄位(如@timestamp),用於標識文檔的寫入或更新時間。

步驟一:準備LogStash環境

LogStash支援不同的源和目標,本文使用的目標庫為PolarSearch,源庫為Elasticsearch 7.10PolarSearch。

  1. 下載並解壓LogStash:請根據您的環境選擇對應的安裝包。本文以Linux x86_64環境8.8.2版本為例。

    說明
    • 不同版本的LogStash在使用上略有差異但核心邏輯一致。

    • 更多LogStash版本,請參見LogStash版本列表

  2. 安裝外掛程式:不同的源庫與目標庫需要安裝不同的外掛程式,請根據您的實際情況選擇安裝。外掛程式倉庫地址,請參見外掛程式倉庫

    • 源庫外掛程式:

      • 若源庫為Elasticsearch,則需要安裝input-elasticsearch外掛程式。當前外掛程式已經預先安裝,您可通過命令查看是否已經安裝。

        # 進入 LogStash 根目錄
        cd /path/to/logstash-8.8.2
        
        # 檢查外掛程式是否已經安裝
        ./bin/logstash-plugin list
        
        # 如果沒有安裝,則執行外掛程式安裝命令
        ./bin/logstash-plugin install logstash-input-elasticsearch
      • 若源庫為OpenSearch,則需要安裝input-opensearch外掛程式。

        # 進入 LogStash 根目錄
        cd /path/to/logstash-8.8.2
        
        # 執行外掛程式安裝命令
        ./bin/logstash-plugin install logstash-input-opensearch
    • 目標庫外掛程式:安裝output-opensearch外掛程式,PolarSearch相容OpenSearch介面,匯入PolarSearch需安裝output-opensearch外掛程式。

      # 進入 LogStash 根目錄
      cd /path/to/logstash-8.8.2
      
      # 執行外掛程式安裝命令
      ./bin/logstash-plugin install logstash-output-opensearch

步驟二:(可選)為來源資料準備時間戳記欄位

若您計划進行增量同步處理(包括全量完成後繼續增量,或對持續寫入的資料進行同步),但源索引中缺少可用的時間戳記欄位(如@timestamp),請參照以下步驟為新寫入的資料自動注入時間戳記。

重要
  • 若源索引中已有此類欄位(如@timestamp),可直接在後續增量備份過程中通過query引用,跳過當前步驟。

  • 資料更新捕獲限制:若您的業務使用POST /_update介面局部更新文檔,該操作不會觸發Ingest Pipeline重新整理時間戳記。因此,這類更新無法被基於時間戳記的增量同步處理捕獲。建議在應用程式層維護一個隨每次變更而更新的時間戳記欄位。

  1. 建立Ingest Pipeline:
    在源庫執行以下命令,建立一個名為add-timestamp-pipeline的管道,它會將文檔的寫入時間_ingest.timestamp存入@timestamp 欄位。

    說明

    _ingest.timestampOpenSearch/Elasticsearch在處理文檔時由服務端自動產生的內部中繼資料,代表文檔實際寫入的時間,精度為毫秒,時區為UTC,不受用戶端時鐘影響。在處理器中需通過三重括弧文法{{{_ingest.timestamp}}}引用,以避免Mustache模板對特殊字元進行轉義。

    PUT _ingest/pipeline/add-timestamp-pipeline
    {
      "description": "為文檔自動注入寫入時間戳記至 @timestamp 欄位",
      "processors": [
        {
          "set": {
            "field": "@timestamp",
            "value": "{{{_ingest.timestamp}}}",
            "override": false 
          }
        }
      ]
    }
    

    參數說明

    參數

    說明

    field

    目標欄位名,此處寫入@timestamp,也可根據實際需要自訂,如ingest_time

    value

    使用三重括弧{{{...}}}文法引用_ingest.timestamp,確保時間戳記原樣寫入,不被Mustache轉義處理。

    override

    • false:表示若文檔中已存在@timestamp欄位則保留原值不覆蓋。

    • true(預設值):始終以寫入時間覆蓋。

  2. 為索引設定預設Pipeline。
    將此Pipeline應用於目標索引,確保所有寫入都自動新增時間戳記。

    • 方式一(推薦,用於新索引):通過索引模板配置。

      PUT _index_template/my-index-template
      {
        "index_patterns": ["your-business-logs-*"],
        "template": {
          "settings": {
            "index.default_pipeline": "add-timestamp-pipeline"
          },
          "mappings": {
            "properties": {
              "@timestamp": {
                "type": "date"
              }
            }
          }
        }
      }
      
    • 方式二(用於已有索引):直接修改索引設定。

      說明

      通過_settings API僅對新寫入的資料生效,已存量文檔不會追溯注入時間戳記。如需為存量資料補充時間戳記,請使用Reindex API 配合pipeline參數重新索引。

      PUT /your-business-logs-index/_settings
      {
        "index.default_pipeline": "add-timestamp-pipeline"
      }
  3. 驗證Pipeline:
    使用_simulate API測試效果,確認返回結果的_source中已包含@timestamp欄位。

    POST _ingest/pipeline/add-timestamp-pipeline/_simulate
    {
      "docs": [
        {
          "_source": {
            "message": "test log entry",
            "level": "INFO"
          }
        }
      ]
    }

    預期結果:

    {
      "docs": [
        {
          "doc": {
            "_source": {
              "message": "test log entry",
              "level": "INFO",
              "@timestamp": "2026-04-08T02:59:32.249592033Z"
            },
            "_ingest": {
              "timestamp": "2026-04-08T02:59:32.249592033ZZ"
            }
          }
        }
      ]
    }
    

步驟三:建立同步設定檔

LogStash根目錄下建立一個synchronization.conf設定檔,並根據您的情境選擇相應的配置。

情境一:全量資料移轉

此配置用於一次性將源庫的指定索引完整複製到目標庫。

相關參數說明

  • input源庫中的index欄位支援使用萬用字元*以同步多個索引。然而,不建議使用全通配邏輯*來複製所有索引,因為這可能會導致不必要的內部索引複製。

  • input源庫中的docinfo欄位,可以擷取原始索引名和文檔ID。

  • output目標庫中index名字等可以通過記錄的metadata讀取,從而保持索引名等不變或在原有名字等元資訊基礎上進行定製。

  • output目標庫中可以增加stdout調試選項可輸出調試資訊。

更多資訊,請參見同步Logstash事件至OpenSearch

調試輸出

如下圖所示,通過該輸出可以觀察到記錄的_indexmetadata及其結構層次。例如,_index欄位的結構層次表明其在output等後續流程中的提取邏輯為:[@metadata][input][opensearch][_index]

重要

不同input外掛程式的metadata提取邏輯存在差異。

image

設定檔樣本

重要
  • 為避免同步不必要的系統內部索引(如.kibana),在配置中指定索引時,不建議使用*.*等全萬用字元。

  • 為確保目標庫的索引配置(如分詞器、欄位類型)與源端一致,建議在同步前,手動在PolarSearch中建立好索引模板。

# synchronization.conf
# 一個從 Elasticsearch/OpenSearch 向 PolarSearch 同步資料的完整配置樣本。

input {
  # 如果源叢集是 Elasticsearch,請將 'opensearch' 替換為 'elasticsearch'。
  # 兩個外掛程式的配置參數基本相同,但中繼資料路徑可能存在差異。
  opensearch {
    # 【必填】源叢集的串連地址,建議使用 HTTPS 協議。
    hosts => ["https://source-cluster-endpoint:9200"]
    # 【必填】源叢集的認證憑據。
    user => "your_source_user"
    password => "your_source_password"

    # 【必填】指定需要同步的索引,支援萬用字元。
    # 為避免同步不必要的內部索引(如 .kibana),不建議使用 "*" 或 ".*"。
    index => "your-business-logs-*"

    # --- 安全配置 ---
    # 如果源叢集啟用了 SSL/TLS,請設定為 true。
    ssl => true
    # 如果源叢集使用自我簽署憑證,取消注釋並指定 CA 憑證路徑。
    # cacert => "/path/to/source_ca.crt"

    # --- 效能與中繼資料 ---
    # 開啟此選項以擷取原始索引名和文檔 ID。
    docinfo => true
    # 設定並發讀取數,建議設定為源索引的主分區數量以最大化讀取效能。
    slices => 4
    # 每次批量擷取的文檔數量。
    size => 1000
    # 滾動查詢的存活時間,確保長任務不會因逾時而中斷。
    scroll => "5m"
  }
}

output {
  opensearch {
    # 【必填】目標 PolarSearch 叢集的串連地址。
    hosts => ["https://polarsearch-cluster-endpoint:9200"]
    # 【必填】目的地組群的認證憑據。
    user => "your_target_user"
    password => "your_target_password"

    # --- 安全配置 ---
    ssl => true
    # 如果目的地組群使用自我簽署憑證,取消注釋並指定 CA 憑證路徑。
    # cacert => "/path/to/polarsearch_ca.crt"

    # --- 索引與文檔 ID ---
    # 從中繼資料中動態讀取並設定索引名,以保持與源端一致。
    # 注意:中繼資料路徑因 input 外掛程式而異,需通過調試輸出確認。
    index => "%{[@metadata][input][opensearch][_index]}"
    # 從中繼資料中讀取並設定文檔 ID,以保持文檔的唯一性。
    document_id => "%{[@metadata][input][opensearch][_id]}"
  }

  # --- 調試輸出(可選) ---
  # 在開發與測試階段,取消此段注釋可在控制台列印資料流資訊。
  # 正式同步時,注釋掉此段以獲得最佳效能。
  # stdout {
  #   codec => rubydebug {
  #     metadata => true
  #   }
  # }
}

參考寫入速率

情境

參考寫入速率

多索引、6分區、8pipeline worker、ECS 816 GB、文檔平均260位元組。

18.67 MB/s, 37883 docs/s。

情境二:增量資料同步

此配置通過定時調度,周期性地拉取源庫中在指定時間視窗內新增或更新的資料。

重要
  • 準備工作:請確保已完成步驟二:(可選)為來源資料準備時間戳記欄位的配置。

  • 啟動時機:建議先完成一次全量資料移轉,再啟動增量同步處理任務。並將增量同步處理的時間查詢起點對齊到全量遷移完成的時刻,避免歷史資料遺漏或新舊資料交叉覆蓋。

  • 調度配置:LogStash 的schedule調度是串列執行的。請確保單次同步任務的執行耗時小於調度周期,否則可能導致部分時間視窗的資料未被採集,造成資料遺漏。建議將query的時間範圍設定得略大於調度周期(例如,每5分鐘調度一次,查詢近6分鐘的資料),以利用等冪寫入特性來覆蓋邊界情況。

設定檔樣本

# synchronization.conf
# 一個從 Elasticsearch/OpenSearch 向 PolarSearch 增量同步處理資料的完整配置樣本。
# 通過定時執行帶時間範圍過濾的查詢,每個調度周期僅拉取指定時間視窗內
# 新寫入或更新的文檔,實現增量資料同步。

input {
  # 如果源叢集是 Elasticsearch,請將 'opensearch' 替換為 'elasticsearch'。
  elasticsearch {
    # 【必填】源叢集的串連地址。
    hosts => ["https://source-cluster-endpoint:9200"]
    # 【必填】源叢集的認證憑據。
    user     => "your_source_user"
    password => "your_source_password"

    # 【必填】指定需要增量同步處理的索引,支援萬用字元。
    index => "your-business-logs-*"

    # --- 增量同步處理核心配置 ---
    # 時間範圍查詢:僅拉取最近 5 分鐘內寫入的文檔。
    # gte: 大於等於目前時間減去 5 分鐘。
    # lte: 小於等於當前分鐘整點(now/m 表示向下取整到分鐘,用於避免拉取尚未寫入完畢的資料)。
    # 時間視窗大小需與 schedule 調度周期保持匹配,防止兩次調度之間出現資料空檔。
    query => '{"query":{"range":{"@timestamp":{"gte":"now-5m","lte":"now/m"}}}}'

    # 定時調度:使用 Cron 文法定義執行循環,以下配置為每分鐘執行一次。
    # 常見樣本:
    #   "* * * * *"     每分鐘執行
    #   "*/5 * * * *"   每 5 分鐘執行
    #   "0 * * * *"     每小時整點執行
    schedule => "* * * * *"

    # 滾動查詢的存活時間,確保分批拉取時上下文不會逾時中斷。
    scroll => "5m"
    # 開啟此選項以擷取原始索引名和文檔 ID。
    docinfo => true
    # 設定並發讀取數,建議設定為源索引的主分區數量以最大化讀取效能。
    slices => 4
    # 每次批量擷取的文檔數量。
    size => 5000

    # --- 安全配置 ---
    # ssl => true
    # cacert => "/path/to/source_ca.crt"
  }
}

# filter(可選): 移除 pipeline 附加的@timestamp欄位
# filter {
#   mutate {
#     remove_field => ["@timestamp"]
#   }
# }

output {
  opensearch {
    # 【必填】目標 PolarSearch 叢集的串連地址。
    hosts    => ["https://polarsearch-cluster-endpoint:9200"]
    # 【必填】目的地組群的認證憑據。
    user     => "your_target_user"
    password => "your_target_password"

    # --- 安全配置 ---
    ssl => true
    # cacert => "/path/to/polarsearch_ca.crt"

    # 從中繼資料中動態讀取索引名,保持與源端一致。
    # 注意:中繼資料路徑因 input 外掛程式而異,需通過調試輸出確認。
    index       => "%{[@metadata][input][elasticsearch][_index]}"
    # 從中繼資料中讀取文檔 ID,實現等冪寫入:同一文檔重複同步時執行更新而非重複插入。
    document_id => "%{[@metadata][input][elasticsearch][_id]}"
  }

  # --- 調試輸出(可選) ---
  # stdout {
  #   codec => rubydebug {
  #     metadata => true
  #   }
  # }
}

步驟四:執行同步與驗證

  1. 啟動任務:在LogStash根目錄下執行以下命令啟動同步任務。

    # 啟動同步任務,-f 參數指定設定檔
    ./bin/logstash -f synchronization.conf

    對於大規模資料同步,建議使用nohupLogStash作為後台服務運行:

    nohup ./bin/logstash -f synchronization.conf &
  2. 等待任務執行完成後,登入目標PolarSearch,檢查索引和資料是否成功建立和寫入。

常見問題

如何確認中繼資料(如索引名)的正確路徑?

output配置中啟用stdout調試輸出。啟動LogStash後,控制台會列印每條文檔的詳細資料,包括[@metadata]對象。從中找到_index_id的確切層級結構,並修改output配置中的路徑。

樣本調試輸出

{
    // ... 其他欄位
    "@metadata": {
        "input" => {
          "opensearch" => {
              "_id": "some-document-id",
              "_index": "your-business-logs-2023.01.01",
              // ... 其他中繼資料
          }
        }
    }
}

根據以上輸出,正確的索引名路徑是%{[@metadata][input][opensearch][_index]}

重要

不同input外掛程式的中繼資料路徑存在差異。使用logstash-input-elasticsearch時,路徑中的opensearch應替換為elasticsearch,即%{[@metadata][input][elasticsearch][_index]}

同步速度很慢,如何最佳化?

  1. 增加slices選項:確保input配置中的slices參數值等於源索引的主分區數。

  2. 增加pipeline.workers:啟動LogStash時,使用--pipeline.workers參數增加並發處理線程數,例如 ./bin/logstash -f synchronization.conf --pipeline.workers 8。此值通常可設定為伺服器的CPU核心數。

  3. 增加LogStashJVM堆大小:編輯config/jvm.options檔案,增大-Xms-Xmx的值,例如-Xms4g -Xmx4g

如何確保目標庫的索引配置(如分詞器、欄位類型)與源端一致?

同步前,從源庫匯出索引的MappingSettings,然後在目標PolarSearch中手動建立對應的索引模板。最後,在LogStashoutput配置中設定manage_template => false,確保LogStash不會覆蓋預設的模板。

增量同步處理時,如何避免遺漏文檔更新?

增量同步處理的時間過濾基於文檔的時間戳記欄位,能否捕獲更新操作取決於更新方式:

  • 若業務側使用POST /_update進行局部更新,該操作不會觸發Ingest Pipeline,@timestamp不會重新整理,因此增量同步處理無法感知此類更新。

  • 若業務側使用完整的index(全量覆蓋寫入)方式更新文檔,則會觸發Pipeline並重新整理@timestamp,增量同步處理可以捕獲。

如果您的業務更新操作以_update為主,建議在業務層面由寫入方主動維護一個隨每次變更重新整理的時間戳記欄位,並以此作為增量同步處理的過濾依據。

增量同步處理任務意外中斷後,如何恢複?

增量同步處理基於時間視窗查詢,無需額外的狀態持久化。重新啟動LogStash 後,任務將按照query中配置的時間範圍(如now-5m)重新拉取最近一個時間視窗內的資料並繼續執行,無需手動幹預。如需從某一記錄點補同步資料,可臨時調整query 中的時間範圍(例如將now-5m改為now-2h)啟動一次性補償同步,完成後再恢複原配置。