Elasticsearch零停机迁移数据

创建索引

创建一个名为my_index的索引

PUT localhost:9200/my_index

创建映射

PUT localhost:9200/my_index/my_type/_mapping
{
    "properties": {
        "name": {
            "type": "text"
        }
    }
}

添加一个文档

PUT localhost:9200/my_index/my_type/2
{
    "name": "李锋镝"
}

查询:

GET localhost:9200/my_index/my_type/2
{
    "_index": "my_index",
    "_type": "my_type",
    "_id": "2",
    "_version": 1,
    "_seq_no": 0,
    "_primary_term": 1,
    "found": true,
    "_source": {
        "name": "李锋镝"
    }
}

可以发现文档所属的索引是my_index

设置别名prod_index指向my_index

PUT localhost:9200/my_index/_alias/prod_index

检测别名是否设置成功

使用

GET localhost:9200/*/_alias/prod_index

或者

GET localhost:9200/my_index/_alias/*

如果成功就会都返回如下的结果:

{
    "my_index": {
        "aliases": {
            "prod_index": {}
        }
    }
}

说明别名设置成功。

使用别名查询文档:

GET localhost:9200/prod_index/my_type/2
{
    "_index": "my_index",
    "_type": "my_type",
    "_id": "2",
    "_version": 1,
    "_seq_no": 0,
    "_primary_term": 1,
    "found": true,
    "_source": {
        "name": "李锋镝"
    }
}

嗯...文档所属的索引同样是my_index

然后可能过了一段时间我们发现my_index中的一个字段的映射不符合我们现今的需求,需要修改这个字段的映射。问题来了,我们不能修改现存的映射,所以我们必须重新索引数据。

重建索引

首先创建一个名为my_index1的索引

PUT localhost:9200/my_index1

创建映射

PUT localhost:9200/my_index1/my_type/_mapping
{
    "properties": {
        "name": {
            "type": "keyword"
        }
    }
}

将数据从my_index中索引到my_index1

POST localhost:9200/_reindex
{
  "source": {
    "index": "my_index"
  },
  "dest": {
    "index": "my_index1"
  }
}

操作成功,返回:

{
    "took": 1159,
    "timed_out": false,
    "total": 2,
    "updated": 0,
    "created": 2,
    "deleted": 0,
    "batches": 1,
    "version_conflicts": 0,
    "noops": 0,
    "retries": {
        "bulk": 0,
        "search": 0
    },
    "throttled_millis": 0,
    "requests_per_second": -1.0,
    "throttled_until_millis": 0,
    "failures": []
}

然后我们查询下数据,看下数据过来了没:

GET localhost:9200/my_index1/my_type/2
{
    "_index": "my_index1",
    "_type": "my_type",
    "_id": "2",
    "_version": 1,
    "_seq_no": 0,
    "_primary_term": 1,
    "found": true,
    "_source": {
        "name": "李锋镝"
    }
}

可以看到通过新的索引已经可以查询到my_index中的数据了。

接下来就是将别名prod_index指到my_index1上,因为一个别名可以指向多个索引,所以我们还需要删除my_index的别名。这个操作需要原子化,所以我们使用_aliases API来操作。

转移索引别名

POST localhost:9200/_aliases
{
    "actions": [
        {
            "remove": {
                "index": "my_index",
                "alias": "prod_index"
            }
        },
        {
            "add": {
                "index": "my_index1",
                "alias": "prod_index"
            }
        }
    ]
}

然后我们使用别名来查询一下我们的数据:

GET localhost:9200/prod_index/my_type/2
{
    "_index": "my_index1",
    "_type": "my_type",
    "_id": "2",
    "_version": 1,
    "_seq_no": 0,
    "_primary_term": 1,
    "found": true,
    "_source": {
        "name": "李锋镝"
    }
}

可以看到我们通过别名查询到的数据的索引已经是my_index1了。

OK,到了这里基本就大功告成,实现了在零停机的情况下从旧索引迁移到新索引了(前提是应用程序里边使用的是别名而不是索引名,这样你就可以在任何时候重建索引,而且别名的开销很小)。

其他

数据量太大,迁移时间很长怎么办?

_reindex API重建索引默认分页大小是1000,可以通过调整这个参数来增加效率。

POST localhost:9200/_reindex
{
  "source": {
    "index": "my_index",
    "size": 5000
  },
  "dest": {
    "index": "my_index1",
    "routing": "=cat"
  }
}

或者使用slices并行处理数据:

POST localhost:9200/_reindex?slices=5&refresh
{
  "source": {
    "index": "my_index"
  },
  "dest": {
    "index": "my_index1"
  }
}

除非注明,否则均为李锋镝的博客原创文章,转载必须以链接形式标明本文链接

本文链接:https://www.lifengdi.com/archives/article/1607

分享到:
订阅
提醒
guest
0 评论
Inline Feedbacks
查看所有评论