Elasticsearch是一個實時的分佈式搜索引擎,爲用戶提供搜索服務,當我們決定存儲某種數據時,在創建索引的時候需要數據結構完整確定下來,與此同時索引的設定和很多固定配置將不能改變。當需要改變索引結構時就需要重建索引。
下面介紹索引重建的3個方案:
方案一:外部數據導入方案
整體介紹
系統架構設計中,一般有關係型數據庫用來存儲數據,Elasticsearch在系統架構裏起到查詢加速的作用。如果是遇到索引重建的操作,待系統模塊發佈新版本後,可以從數據庫中將數據查詢出來,重新寫入ES即可。
詳細操作步驟
- 微服務模塊從數據庫裏查詢數據的總數和批次信息,將每個批次的分頁信息發給MQ,分頁信息包含查詢條件和偏移量
- 微服務根據接收到的分頁信息,從數據庫獲得數據,根據新索引結構的定義,將數據組裝成JSON,並執行bulk命令,將數據寫入es
方案特點
微服務模塊實例可能會部署多個,數據是分批處理的,批次信息會一次性發給MQ,利用MQ的異步處理機制,可以充分的利用多實例的併發優勢,加速數據重建的速度。
方案缺點
- 對數據庫造成讀取壓力,短時間內大量的讀操作,會佔用數據庫的硬件資源。
- 網絡帶寬佔用多,從數據庫寫入ES會有大量的數據傳輸帶寬佔用
方案二:基於scroll+bulk+索引別名方案
整體介紹
利用java客戶端做持續的scroll查詢和bulk命令寫入,數據自給自足,不依賴其他數據源。
執行步驟
假設原索引名稱是item,新的索引名稱爲item_new,java客戶端使用別名item_alias鏈接ES,該別名指向原索引item。
- 先建立一個別名
PUT /item/_alias/item_alias
- 新建索引item_new,將mapping信息等按新的格式定義好
- 使用scroll api將數據批量查詢出來,這個1m就是保存搜索的上下文環境的時間。
GET /item/_search?scroll=1m
{
"query": {
"match_all": {}
},
"sort": ["_doc"],
"size": 2
}
- 採用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}
- 反覆執行步驟3和4(注意步驟3中,需要指定上一次查詢的scroll_id)
GET /_search/scroll
{
"scroll":"1m",
"scroll_id":"步驟3查出來的值"
}
- 切換別名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做了一層封裝,能夠對文檔重建索引不需要任何插件或外部工具。
- 基礎使用:
POST _reindex
{
"source": {
"index": "item"
},
"dest": {
"index": "item_new"
}
}
注意: 如果不手動創建新索引book_new的mapping信息,那麼Elasticsearch將啓動自動映射模板對數據進行類型映射,可能不是期望的類型,這點要注意一下
- 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進行更新,遵循樂觀鎖機制
- 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"
}
}
- query支持
reindex api支持數據過濾、數據排序、size設置、_source選擇等,也支持腳本執行。
POST _reindex
{
"size": 10,
"source": {
"index": "item",
"query": {
"term": {
"title": {
"value": "手機"
}
}
}
},
"dest": {
"index": "item_new",
"op_type": "create"
}
}