Elasticsearch學習系列五(零停機索引重建)

Elasticsearch是一個實時的分佈式搜索引擎,爲用戶提供搜索服務,當我們決定存儲某種數據時,在創建索引的時候需要數據結構完整確定下來,與此同時索引的設定和很多固定配置將不能改變。當需要改變索引結構時就需要重建索引。

下面介紹索引重建的3個方案:

方案一:外部數據導入方案

整體介紹

系統架構設計中,一般有關係型數據庫用來存儲數據,Elasticsearch在系統架構裏起到查詢加速的作用。如果是遇到索引重建的操作,待系統模塊發佈新版本後,可以從數據庫中將數據查詢出來,重新寫入ES即可。

詳細操作步驟

  1. 微服務模塊從數據庫裏查詢數據的總數和批次信息,將每個批次的分頁信息發給MQ,分頁信息包含查詢條件和偏移量
  2. 微服務根據接收到的分頁信息,從數據庫獲得數據,根據新索引結構的定義,將數據組裝成JSON,並執行bulk命令,將數據寫入es

方案特點

微服務模塊實例可能會部署多個,數據是分批處理的,批次信息會一次性發給MQ,利用MQ的異步處理機制,可以充分的利用多實例的併發優勢,加速數據重建的速度。

方案缺點

  1. 對數據庫造成讀取壓力,短時間內大量的讀操作,會佔用數據庫的硬件資源。
  2. 網絡帶寬佔用多,從數據庫寫入ES會有大量的數據傳輸帶寬佔用

方案二:基於scroll+bulk+索引別名方案

整體介紹

利用java客戶端做持續的scroll查詢和bulk命令寫入,數據自給自足,不依賴其他數據源。

執行步驟

假設原索引名稱是item,新的索引名稱爲item_new,java客戶端使用別名item_alias鏈接ES,該別名指向原索引item。

  1. 先建立一個別名
PUT /item/_alias/item_alias
  1. 新建索引item_new,將mapping信息等按新的格式定義好
  2. 使用scroll api將數據批量查詢出來,這個1m就是保存搜索的上下文環境的時間。
GET /item/_search?scroll=1m
{
  "query": {
    "match_all": {}
  },
  "sort": ["_doc"],
  "size": 2
}
  1. 採用bulk api將scroll查出來的數據,批量寫入新索引
POST /_bulk
{"index":{"_index":"item_new","_id":"tr6YgYEB9TD2fYkcFzjY"}}
{"title":"小米手機","price":"2688","images":"http://image.lagou.com/12479122.jpg","createTime":"2022-02-01 12:02:02","lifecycle":1}
  1. 反覆執行步驟3和4(注意步驟3中,需要指定上一次查詢的scroll_id)
GET /_search/scroll
{
  "scroll":"1m",
  "scroll_id":"步驟3查出來的值"
}
  1. 切換別名item_alias到新的索引item_new上面,此時java客戶端讓使用別名訪問,不需要修改代碼,也不需要停機。
POST /_aliases
{
  "actions": [
    {
      "remove": {
        "index": "item",
        "alias": "item_alias"
      }
    }
    ,{
      "add": {
         "index": "item_new",
        "alias": "item_alias"
      }
    }
  ]
}

方案特點

在數據傳輸上自給自足,不依賴其他數據源。網絡傳輸佔用帶寬較小。

另外在java客戶端訪問es集羣時,使用別名是一個好習慣。

方案三:Reindex API方案

ES v6.3.1已經支持Reindex API,它對scroll、bulk做了一層封裝,能夠對文檔重建索引不需要任何插件或外部工具。

  1. 基礎使用:
POST _reindex
{
  "source": {
    "index": "item"
  },
  "dest": {
    "index": "item_new"
  }
}

注意: 如果不手動創建新索引book_new的mapping信息,那麼Elasticsearch將啓動自動映射模板對數據進行類型映射,可能不是期望的類型,這點要注意一下

  1. version_type屬性

使用reindex api也是創建快照後再執行遷移的,這樣目標索引的數據可能會與原索引有差異,version_type屬性可以決定樂觀鎖併發處理的規則

POST _reindex
{
  "source": {
    "index": "item"
  },
  "dest": {
    "index": "item_new",
    "version_type": "internal"
  }
}

version_type屬性含義如下:

  • internal:直接拷貝文檔到目標索引,對相同的type、文檔ID直接進行覆蓋,默認值
  • external:遷移文檔到目標索引時,保留version信息,對目標索引中不存在的文檔進行創建,已
    存在的文檔按version進行更新,遵循樂觀鎖機制
  1. op_type屬性和conflicts屬性

如果op_type設置爲create,那麼遷移時只在目標索引中創建ID不存在的文檔,已存在的文檔,會提示錯誤,如下請求:

POST _reindex
{
  "source": {
    "index": "item"
  },
  "dest": {
    "index": "item_new",
    "op_type": "create"
  }
}

錯誤信息會比較多,如果加上"conflicts":"proceed"配置項,那麼衝突信息將不展示,只展示衝突的文檔數量,請求和響應結果將變成這樣:

POST _reindex
{
  "conflicts": "proceed", 
  "source": {
    "index": "item"
  },
  "dest": {
    "index": "item_new",
    "op_type": "create"
  }
}
  1. query支持

reindex api支持數據過濾、數據排序、size設置、_source選擇等,也支持腳本執行。

POST _reindex
{
  "size": 10, 
  "source": {
    "index": "item",
    "query": {
      "term": {
        "title": {
          "value": "手機"
        }
      }
    }
  },
  "dest": {
    "index": "item_new",
    "op_type": "create"
  }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章