教你如何在 elasticsearch 中重建索引

序言

image

Elasticsearch 是一個實時的分佈式搜索分析引擎。Teambition 使用 Elastisearch 做爲搜索引擎,爲用戶提供搜索服務,當咱們決定存儲某種數據時,咱們須要使用PUT /teambition建立索引,在建立索引的時候須要將數據結構完整肯定下來,於此同時索引的設定和不少固定配置將用不能改變。當須要改變數據結構時,就須要從新創建索引,爲此,Elastic團隊提供了不少輔助工具幫助開發人員進行重建索引。git

決定是否須要重建?

重建時至關痛苦的,若是沒有很好的基礎,服務可能中斷,當數據量很是大時,重建恢復時間可能很長,甚至在重建過程當中出錯等等。因此,沒有萬不得已的狀況下仍是儘可能避免重建索引。Teambition 重建索引的理由略,由於這並不重要。github

使用正確的工具

kibana 是 Elasticsearch 的最佳拍檔,從 ES 5.0 開始,Kibana 強大的功能可以替代幾乎全部舊時代 ES 1.x 和 ES 2.x 的插件。關鍵是人家仍是免費的! json

先決條件

正在運行的服務必須使用別名(alias)來訪問索引(index),緣由很簡單,搜索服務最終要使用重建的索引,原始的索引將被刪除。若是你的服務正在直接使用索引名,在重建前建立別名,更新服務。api

POST /_aliases
{
  "actions": [
    {
      "add": {
        "index": "teambition", // 原有索引
        "alias": "teambition_latest" // 服務的別名
      }
    }
  ]
}
複製代碼



先決條件2

記得查看 Elasticsearch 的 Disk Usage,若是不夠,請先申請好足夠的空間。bash

建立新索引

和建立普通索引同樣建立新索引。這裏值得一提的時,當數據量很大的時候,須要設置刷新時間間隔,在此期間寫入的數據不能搜到,從而提升重建速度:refresh_intervals = -1, number_of_replicas = 0。實踐告訴我,大概會提升100% ~ 400%的提高。數據結構

PUT /teambition_20180328
{
  "settings": {...},
  "mapping": {...}
}
複製代碼

記錄同步數據的偏移值(offset)

Teambition使用Kafka把MongoDB中的數據導入到Elasticsearch中,若是沒有kafka,亦可讀取oplog的數據寫入Elasticsearch。不管使用哪一種同步數據的方式,都須要記錄同步數據的offset。重建索引可能很是耗時,在這段時間內,同步進程仍然在向舊索引更新數據,此時重建索引是沒法更新這些新數據的。這裏記錄的方法就很少說了,Teambition 使用 kafka-admin 的API記錄 offset。app

開始重建索引

使用 Elasticsearch 團隊提供的 reindex api 就能夠將數據 copy 到新索引中。這裏幾條路能夠選:分佈式

  1. 當只是改變 mapping 數據結構時,能夠僅僅使用 reindex api 便可。例如:刪除字段,更新字段分詞方式等。
  2. 當須要寫入新的字段,新的字段是由老的字段計算獲得時,可使用script參數。例如,計算某條數據某字段的總和。script 有不少坑,當 script 出錯時,reindex 跑了好久以後失敗,即便將數據恢復,也須要從新跑 reindex。
  3. 當含有很複雜的邏輯時,額,仍是本身寫程序吧。

調用 reindex 接口,接口將會在 reindex 結束後返回,而接口返回超時只有30秒,若是 reindex 時間過長,建議加上wait_for_completion=false的參數條件,這樣 reindex 將直接返回taskId工具

POST _reindex?wait_for_completion=false
{
  "source": {
    "index": "teambition"
  },
  "dest": {
    "index": "teambition_20180328"
  },
  "script": {...}
}
複製代碼

重建索引中

重建索引很是耗時,喝杯咖啡歇一下子吧(順便去打個球,睡個覺,旅個遊)。 搜索引擎

在沒有設置 refresh_intervalsnumber_of_replicas 時,reindex 的速度在 500~1000 doc/sec, 若是包含 script 時可能會更低。設置以後,能夠到 4000~8000 doc/sec。 Teambition 70M Documents 大概耗時4小時。

可使用GET _tasks/{taskID}能夠看到重建進程,其中包含耗時,剩餘doc數量等信息。

若是發現錯誤,可使用PUT _tasks/{taskID}/cancel接口放棄任務,從頭再來。

恢復同步數據

重建索引結束後,別忘了在setting中的將number_of_replicasrefresh_intervals設爲原有值. 啓動新的同步索引的進程(從記錄 offset 開始同步)

創建新的alias

須要在同時綁定創建的新索引以及解綁舊索引,語句以下:

POST _aliases
{
  "actions": [{"add": {
    "index": "teambition_20180328",
    "alias": "teambition_latest"
  }}, {"remove": {
    "index": "teambition",
    "alias": "teambition_latest"
  }}]
}
複製代碼

刪掉index

刪除舊的 index,釋放磁盤空間;中止原有同步進程。

DELETE teambition
複製代碼

總結

修改索引真的是一件費時費力的工做,特別是若是發生了錯誤,整我的都很差了。因此仍是在建立索引的時候儘可能想好可否知足需求,固然你們都知道這幾乎是不可能的,由於存在着萬惡的產品經理。

這裏還有一個很重要的內容沒有詳細介紹就是同步進程,前面提到同步進程是將 MongoDB 的數據同步到 ES 中去的程序,這個程序同時還須要有能力暫停同步,重複同步的等能力。

相關文章
相關標籤/搜索