索引别名和零停机时间

前面提到的重新索引过程中的问题是必须更新你的应用,来使用另一个索引名。索引别名正是用来解决这个问题的!

索引 别名 就像一个快捷方式或软连接,可以指向一个或多个索引,也可以给任何需要索引名的 API 使用。别名带给我们极大的灵活性,允许我们做到:

  • 在一个运行的集群上无缝的从一个索引切换到另一个
  • 给多个索引分类(例如,last_three_months
  • 给索引的一个子集创建 视图

我们以后会讨论更多别名的使用场景。现在我们将介绍用它们怎么在零停机时间内从旧的索引切换到新的索引。

这里有两种管理别名的途径:_alias 用于单个操作,_aliases 用于原子化多个操作。

在这一章中,我们假设你的应用采用一个叫 my_index 的索引。而事实上,my_index 是一个指向当前真实索引的别名。真实的索引名将包含一个版本号:my_index_v1, my_index_v2 等等。

开始,我们创建一个索引 my_index_v1,然后将别名 my_index 指向它:

  1. PUT /my_index_v1 <1>
  2. PUT /my_index_v1/_alias/my_index <2>

<1> 创建索引 my_index_v1

<2> 将别名 my_index 指向 my_index_v1

你可以检测这个别名指向哪个索引:

  1. GET /*/_alias/my_index

或哪些别名指向这个索引:

  1. GET /my_index_v1/_alias/*

两者都将返回下列值:

  1. {
  2. "my_index_v1" : {
  3. "aliases" : {
  4. "my_index" : { }
  5. }
  6. }
  7. }

然后,我们决定修改索引中一个字段的映射。当然我们不能修改现存的映射,索引我们需要重新索引数据。首先,我们创建有新的映射的索引 my_index_v2

  1. PUT /my_index_v2
  2. {
  3. "mappings": {
  4. "my_type": {
  5. "properties": {
  6. "tags": {
  7. "type": "string",
  8. "index": "not_analyzed"
  9. }
  10. }
  11. }
  12. }
  13. }

然后我们从将数据从 my_index_v1 迁移到 my_index_v2,下面的过程在【重新索引】中描述过了。一旦我们认为数据已经被正确的索引了,我们就将别名指向新的索引。

别名可以指向多个索引,所以我们需要在新索引中添加别名的同时从旧索引中删除它。这个操作需要原子化,所以我们需要用 _aliases 操作:

  1. POST /_aliases
  2. {
  3. "actions": [
  4. { "remove": { "index": "my_index_v1", "alias": "my_index" }},
  5. { "add": { "index": "my_index_v2", "alias": "my_index" }}
  6. ]
  7. }

这样,你的应用就从旧索引迁移到了新的,而没有停机时间。

提示:

即使你认为现在的索引设计已经是完美的了,当你的应用在生产环境使用时,还是有可能在今后有一些改变的。

所以请做好准备:在应用中使用别名而不是索引。然后你就可以在任何时候重建索引。别名的开销很小,应当广泛使用。