社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Elasticsearch

教你如何在 elasticsearch 中重建索引

TeambitionNG • 5 年前 • 411 次点击  

教你如何在 elasticsearch 中重建索引

序言

image

Elasticsearch 是一个实时的分布式搜索分析引擎。Teambition 使用 Elastisearch 作为搜索引擎,为用户提供搜索服务,当我们决定存储某种数据时,我们需要使用PUT /teambition创建索引,在创建索引的时候需要将数据结构完整确定下来,于此同时索引的设定和很多固定配置将用不能改变。当需要改变数据结构时,就需要重新建立索引,为此,Elastic团队提供了很多辅助工具帮助开发人员进行重建索引。

决定是否需要重建?

重建时相当痛苦的,如果没有很好的基础,服务可能中断,当数据量非常大时,重建恢复时间可能很长,甚至在重建过程中出错等等。所以,没有万不得已的情况下还是尽量避免重建索引。Teambition 重建索引的理由略,因为这并不重要。

使用正确的工具

kibana 是 Elasticsearch 的最佳拍档,从 ES 5.0 开始,Kibana 强大的功能能够替代几乎所有旧时代 ES 1.x 和 ES 2.x 的插件。关键是人家还是免费的!

先决条件

正在运行的服务必须使用别名(alias)来访问索引(index),原因很简单,搜索服务最终要使用重建的索引,原始的索引将被删除。如果你的服务正在直接使用索引名,在重建前创建别名,更新服务。

POST /_aliases
{
  "actions": [
    {
      "add": {
        "index": "teambition", // 原有索引
        "alias": "teambition_latest" // 服务的别名
      }
    }
  ]
}

先决条件2

记得查看 Elasticsearch 的 Disk Usage,如果不够,请先申请好足够的空间。

创建新索引

和创建普通索引一样创建新索引。这里值得一提的时,当数据量很大的时候,需要设置刷新时间间隔,在此期间写入的数据不能搜到,从而提高重建速度: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。

开始重建索引

使用 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 中去的程序,这个程序同时还需要有能力暂停同步,重复同步的等能力。


今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/t/2WUuL90J0g
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/11983
 
411 次点击