天天看点

Reindex API — Elastic Stack 实战手册

Reindex API — Elastic Stack 实战手册
https://developer.aliyun.com/topic/download?id=1295 · 更多精彩内容,请下载阅读全本《Elastic Stack实战手册》 https://developer.aliyun.com/topic/download?id=1295 https://developer.aliyun.com/topic/es100 · 加入创作人行列,一起交流碰撞,参与技术圈年度盛事吧 https://developer.aliyun.com/topic/es100

创作人:杨松柏

什么是 Reindex

将文档从源索引复制到目的地索引,称之为 Reindex。

在 Reindex 时可以进行数据的丰富、缩减以及字段的变更等。Reindex 可以简单的理解为 Scroll+Bulk_Insert。source 和 dest 都可以是已存在的索引、索引别名或数据流(Data Stream)。

此外,使用 Reindex 需要注意以下几点:

  • 源和目的不能相同,比如不能将数据流 Reindex 给它自身
  • 源索引的文档中 _source 字段必须开启。
  • Reindex不会复制源的 setting 和源所匹配的模板,因此在调用 _reindex 前,你需要设置好目的索引 (action.auto_create_index 为 false 或者 -.* 时)。
  • 目标索引的 mapping,主分片数,副本数等推荐提前配置。

Reindex的主要场景:

  • 集群升级:将数据从旧集群远程 Reindex 到新集群
  • 索引备份
  • 数据重构

前置要求

如果 Elasticsearch 集群配置了安全策略和权限策略,则进行 Reindex 必须拥有以下权限:

  • 读取源的数据流、索引、索引别名等索引级别权限
  • 对于目的数据流、索引、索引别名的写权限
  • 如果需要使用 Reindex API 自动创建数据流和索引,则必须拥有对目的数据流、索引、索引别名的 auto_configure、create_index 或者 manage 等索引级别权限。
  • 如果源为远程的集群,则 source.remote.user 用户必须拥有集群监控权限,和读取源索引、源索引别名、源数据流的权限。

如果 Reindex 的源为远程集群,必须在当前集群的请求节点 elasticsearch.yml 文件配置远程白名单 reindex.remote.whitelist。

自动创建数据流,需要提前配置好数据流的匹配索引模板,

详情可参看 Set up a data stream: https://www.elastic.co/guide/en/elasticsearch/reference/7.11/set-up-a-data-stream.html

API 介绍

RESTful API

POST /_reindex           

Query parameters

refresh

可选参数,枚举类型 (true,false,wait_for),默认值为 false。

如果设置为 true, Elasticsearch 刷新受当前操作影响的数据,能够被立即搜索(即立即刷新,但是会对 Elasticsearch 的性能有一定的影响)。如果为 wait_for,则等待刷新以使当前操作对搜索可见,等待时间为默认为 1s(index.refresh_interval)。如果为 false,本次请求不执行刷新。

timeout

可选参数,时间值(time units),默认值为 1 分钟;每个索引周期中等待索引自动创建、动态映射更新,和等待活跃健康分片等的时间。该参数可以确保 Elasticsearch 在失败之前,基本等待的超时时间。实际等待时间可能更长,特别是在发生多个等待时。

wait_for_active_shards

可选参数,参数类型 string,默认值为 1(即只要一个分片处于活跃就可以执行该操作)。在执行 Reindex 之前索引必须处于活动状态的分片副本数,可以设置为 all 或者小于 number_of_replicas+1 的任何正整数,比如你的索引主分片数目为 3,副本设置为 2,那么可以设置的最大正整数为 3,即副本份数加 1 (主分片)。

#因为实操集群只有三个节点,如下索引将会出现副本分片无法分配,
#index.routing.allocation.total_shards_per_node
#控制每个该索引只允许每个节点分配一个分片
PUT reindex_index-name-2
{
  "settings" :{
    "index" :{
      "number_of_shards" : "3",
      "number_of_replicas" : "2"
    },
    "index.routing.allocation.total_shards_per_node":1
  }
}
#插入一条数据
PUT reindex_index-name-1/_bulk
{ "index":{ } }
{ "@timestamp": "2099-05-06T16:21:15.000Z", "message": "192.0.2.42 - - [06/May/2099:16:21:15 +0000] \"GET /images/bg.jpg HTTP/1.0\" 200 24736" }

#重建索引
POST _reindex?wait_for_active_shards=2&timeout=5s
{
  "source": {
    "index": "reindex_index-name-1"
  },
  "dest": {
    "index": "reindex_index-name-2"
  }
}           

由于

reindex_index-name-2

只有主分片分配成功,所以上面的

_reindex

将失败

{
  "took" : 5002,
  "timed_out" : false,
  "total" : 1,
  "updated" : 0,
  "created" : 0,
  "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" : [
    {
      "index" : "reindex_index-name-2",
      "type" : "_doc",
      "id" : "U_i8VnkBYYHWy1KlBJjc",
      "cause" : {
        "type" : "unavailable_shards_exception",
        "reason" : "[reindex_index-name-2][0] Not enough active copies to meet shard count of [2] (have 1, needed 2). Timeout: [5s], request: [BulkShardRequest [[reindex_index-name-2][0]] containing [index {[reindex_index-name-2][_doc][U_i8VnkBYYHWy1KlBJjc], source[{ \"@timestamp\": \"2099-05-06T16:21:15.000Z\", \"message\": \"192.0.2.42 - - [06/May/2099:16:21:15 +0000] \\\"GET /images/bg.jpg HTTP/1.0\\\" 200 24736\" }]}]]"
      },
      "status" : 503
    }
  ]
}           

wait_for_completion

可选参数,参数类型

Boolean

,默认为

true

。如果为

true

,则请求为阻塞同步方式,请求会等到操作完成才返回。

requests_per_second

integer

,默认为 -1(不进行限制);限制请求的每秒子请求数。

require_alias

Boolean

true

true

dest.index

必须为索引别名。

scroll

可选参数,参数类型为时间类型( time units),指定滚动搜索时索引的一致视图应保持多长时间。

slices

integer

,默认值为1(不切分成多个子任务);该参数表示将一个任务切分成多少个子任务,并行执行。

max_docs

integer

,默认值为对应索引的所有文档;要处理的最大文档数。

Request Body

conflicts

可选参数,参数类型枚举类型,默认为

abort

;设置为

proceed

,即使发生文档冲突也继续

reindexing

source

  • index

必填参数,参数类型

string

;值可以为数据流、索引名字、索引别名,如果源有多个,也可以接受逗号分隔的数据源数组。

  • integer

    ;要被重新索引的最大文档数目。
  • query

    可选参数,参数类型查询对象(query object),按查询 DSL 过滤需要重新索引的文档。

  • remote

    remote 的子参数可接受如下:

参数 是否必填 类型 说明
host string 索引 pattern 名源索引所在远程 ES 集群中任一节点地址;如果是需要从远程 集群复制数据,则该参数必填。
username 与远程主机进行身份验证的用户名;当远程集群需要认证时必填。
password 与远程主机进行身份验证的密码;当远程集群需要认证时必填。
socket_timeout 时间类型 默认为 30 秒;远程套接字读取超时。
connect_timeout 默认为 30 秒;远程连接超时时间。
  • size

可选参数,参数类型 integer; 每批要索引的文档数(批处理),在远程索引时确保批处理能够放在堆上缓冲区,缓冲区的默认大小为100 MB。

  • slice

slice的子参数可接受如下:

id integer 进行手动切片时的,设置的切片 id
max 切片总数。
  • sort

可选参数,参数类型 list;以逗号分隔的 : 对列表(比如name:desc),用于在获取源索引文档时,按照 sort 中字段值的排序要求进行排序。通常与

max_docs

参数结合使用,以控制哪些文档需要被重新索引。

注意:sort 参数在 7.6 版本已经被标注弃用,不建议在 Reindex 中进行排序。 Reindex 中的排序不能保证按顺序索引文档,并阻止 Reindex 的进一步发展,如恢复能力和性能改进。如果与结合使用

max_docs

,请考虑改为使用查询过滤器。

  • _source

string

,默认值为 true。该参数可以用于选择文档中哪些字段需要进行重新索引。如果设置为 true,将会重索引文档中的所有字段。

dest

必填参数,参数类型 string;该参数表示目的地的表,值可以为数据流、索引名字、索引别名。

  • version_type

可选参数,参数类型枚举;用于索引操作的版本控制;枚举值包括:

internal

external

external_gt

external_gte

详情参看 Version types : https://www.elastic.co/guide/en/elasticsearch/reference/7.11/docs-index_.html#index-version-types
  • op_type

可选参数,参数类型枚举,默认为 index,枚举值包括:

index

create

;如果设置为

create

,则目标索引不存在该文档就创建(可用于

reindex

续传补偿)。注意:如果

dest

是数据流,必须设置为

create

,因为数据流只做

append

  • type

string

,默认值为

_doc

;被重建索引的文档中文档类型;注意:该参数在 Elasticsearch 6 版本中已经标记弃用,已经没有任何实际意义。

script

可选参数,参数类型 string;重新索引时用于更新文档 source 或元数据的脚本 .

  • lang

可选参数,参数类型枚举;支持的脚本语言:

painless

,

expression

mustache

java

更多脚本语言,请参考 Scripting: https://www.elastic.co/guide/en/elasticsearch/reference/7.11/modules-scripting.html

Response Body

执行

_reindex

时的,响应体参数释意:

字段
took 整个操作花费的总毫秒数
timed_out Boolean 如果在重新索引期间出现的任何请求超时,则此标志设置为 true。
total 成功处理的文档数
updated 已成功更新的文档数,即重新索引的文档,在 dest 索引中存在具有相同 ID 的文档,并且更新成功的
created 成功创建的文档数
deleted 成功删除的文档数
batches 由重新索引回调的滚动响应数
noops 由于重新索引的脚本为 ctx.op 返回 noop 值而被忽略的文档数
version_conflicts 重新索引命中的版本冲突数
retries 重索引尝试的重试次数;bulk 是重试的批量操作数,search 是重试的搜索操作数
throttled_millis 请求休眠以符合 requests_per_second
在重新索引期间每秒有效执行的请求数
throttled_until_millis 此字段在 _reindex 响应中应始终等于零;该参数只有在使用任务 API(Task API)时才有意义,在任务 API 中,它指示下次再次执行限制请求的时间,以便符合每秒的请求数
failures 数组 如果进程中有任何不可恢复的错误,则返回失败数组。如果数组不为空,那么请求会因为这些失败而中止。重新索引是使用批处理实现的,任何失败都会导致整个进程中止,但当前批处理中的所有失败都会收集到数组中。你可以使用 conflicts 参数,避免因为版本冲突而中止重建索引 Reindex 的一些技巧

异步执行 Reindex

如果请求的查询参数

wait_for_completion

设置为

false

,Elasticsearch 将会执行一些预检查,然后发起一个

task

,来运行你的 Reindex 任务,并立即返回你一个

taskid

,然后你可以通过这个

taskid

,去查看任务的运行结果,运行结果记录在系统索引

.tasks

;如果任务执行完成,你可以删除掉该文档,以使 Elasticsearch 释放空间。

#异步执行 reindex 任务
POST _reindex?wait_for_completion=false
{
  "source": {
    "index": "reindex_index-name-1"
  },
  "dest": {
    "index": "reindex_index-name-2"
  }
}

#返回立即返回的任务 id
{
  "task" : "ydZx8i8HQBe69T4vbYm30g:20987804"
}

#查看任务的运行情况
GET _tasks/ydZx8i8HQBe69T4vbYm30g:20987804
#response返回结果
{
  "completed" : true,
  "task" : {
    "node" : "ydZx8i8HQBe69T4vbYm30g",
    "id" : 20987804,
    "type" : "transport",
    "action" : "indices:data/write/reindex",
    "status" : {
      "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
    },
    "description" : "reindex from [reindex_index-name-1] to [reindex_index-name-2][_doc]",
    "start_time_in_millis" : 1620539345400,
    "running_time_in_nanos" : 84854825,
    "cancellable" : true,
    "headers" : { }
  },
  "response" : {
    "took" : 82,
    "timed_out" : false,
    "total" : 2,
    "updated" : 0,
    "created" : 2,
    "deleted" : 0,
    "batches" : 1,
    "version_conflicts" : 0,
    "noops" : 0,
    "retries" : {
      "bulk" : 0,
      "search" : 0
    },
    "throttled" : "0s",
    "throttled_millis" : 0,
    "requests_per_second" : -1.0,
    "throttled_until" : "0s",
    "throttled_until_millis" : 0,
    "failures" : [ ]
  }
}

#实际任务运行结果会记录在 .tasks 索引
GET  .tasks/_doc/ydZx8i8HQBe69T4vbYm30g:20987804
#返回值如下
{
  "_index" : ".tasks",
  "_type" : "_doc",
  "_id" : "ydZx8i8HQBe69T4vbYm30g:20987804",
  "_version" : 1,
  "_seq_no" : 1,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "completed" : true,
    "task" : {
      "node" : "ydZx8i8HQBe69T4vbYm30g",
      "id" : 20987804,
      "type" : "transport",
      "action" : "indices:data/write/reindex",
      "status" : {
        "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
      },
      "description" : "reindex from [reindex_index-name-1] to [reindex_index-name-2][_doc]",
      "start_time_in_millis" : 1620539345400,
      "running_time_in_nanos" : 84854825,
      "cancellable" : true,
      "headers" : { }
    },
    "response" : {
      "took" : 82,
      "timed_out" : false,
      "total" : 2,
      "updated" : 0,
      "created" : 2,
      "deleted" : 0,
      "batches" : 1,
      "version_conflicts" : 0,
      "noops" : 0,
      "retries" : {
        "bulk" : 0,
        "search" : 0
      },
      "throttled" : "0s",
      "throttled_millis" : 0,
      "requests_per_second" : -1.0,
      "throttled_until" : "0s",
      "throttled_until_millis" : 0,
      "failures" : [ ]
    }
  }
}           

多源重建索引

如果有许多源需要重新索引,通常最好一次 Reindex 一个源的索引,而不是使用

glob

模式来选取多个源。这样如果出现任何的错误,你可以删除有问题部分,然后选择特定的源重新索引(

dest

op_type

可以设置为

create

只重索引缺失的文档);另外一个好处,你可以并行运行这些

reindex

任务。

#!/bin/bash
for index in i1 i2 i3 i4 i5; do
  curl -H Content-Type:application/json -XPOST localhost:9200/_reindex?pretty -d'{
    "source": {
      "index": "'$index'"
    },
    "dest": {
      "index": "'$index'-reindexed"
    }
  }'
done           

对 Reindex 限流

设置

requests_per_second

为任意的正十进制数(如 1.4,6,...1000等),以限制批量操作

_reindex

索引的速率。通过在每个批处理中,设置等待时间来限制请求;可以通过设置 requests_per_second=-1,来关闭限流操作。

限流是通过在每个批处理之间设置等待时间,因此 _reindex 在内部使用 scroll 的超时时间,应当将这个等待时间考虑进去。等待时间=批大小/requests_per_second - 批写入耗时;默认情况下,批处理大小为 1000,因此如果 requests_per_second 设置为500:

target_time = 1000 / 500 per second = 2 seconds
wait_time = target_time - write_time = 2 seconds - 0.5 seconds = 1.5 seconds           

由于批处理是作为单个

_bulk

请求发出的,因此较大的批处理大小,会导致 Elasticsearch 创建许多请求,然后等待一段时间,再开始下一组请求;这种情况可能会造成 Elasticsearch 周期性的抖动。

动态调整限流

可以使用

_rethrottle

API 在正在运行的重新索引上更改

requests_per_second

的值:

POST _reindex/r1A2WoRbTwKZ516z6NEs5A:36619/_rethrottle?requests_per_second=-1           

taskid

可以通过 task API 进行获取。重新调整

requests_per_second

,如果是加快查询速度则可以立即生效,如果是降低查询速度,则需要在完成当前批处理后生效,这样可以避免 scroll 超时。

切片

Reindex 支持切片 scroll 以并行化重新索引过程,从而提高 Reindex 的效率。

注意:如果源索引是在远程的 Elasticsearch 集群,是不支持手动或自动切片的。

手动切片

通过为每个请求提供切片 ID 和切片总数。

示例如下:

POST _reindex
{
  "source": {
    "index": "my-index-000001",
    "slice": {
      "id": 0,
      "max": 2
    }
  },
  "dest": {
    "index": "my-new-index-000001"
  }
}

POST _reindex
{
  "source": {
    "index": "my-index-000001",
    "slice": {
      "id": 1,
      "max": 2
    }
  },
  "dest": {
    "index": "my-new-index-000001"
  }
}           

可以通过以下方式验证此功能

#避免还没有形成 segments,文档不可见
GET _refresh
#查看文档的个数
GET my-new-index-000001/_count
#或者
POST my-new-index-000001/_search?size=0&filter_path=hits.total           

返回结果如下

{
  "hits": {
    "total" : {
        "value": 120,
        "relation": "eq"
    }
  }
}           

自动切片

还可以使用 Sliced scroll 基于文档

_id

进行切片,让

_reindex

自动并行化;通过设定 slices 参数的值来实现。

示例如下

POST _reindex?slices=5&refresh
{
  "source": {
    "index": "my-index-000001"
  },
  "dest": {
    "index": "my-new-index-000001"
  }
}           
POST my-new-index-000001/_search?size=0&filter_path=hits.total           
{
  "hits": {
    "total" : {
        "value": 120,
        "relation": "eq"
    }
  }
}           

slices

auto

会让 Elasticsearch 选择要使用的切片数。此设置将每个分片使用一个切片,直到达到某个限制。如果有多个源,它将基于分片数量最少的索引或 Backing index 确定切片数。

POST _reindex?slices=auto&refresh
{
  "source": {
    "index": "my-index-000001"
  },
  "dest": {
    "index": "my-new-index-000001"
  }
}
# 由源码可知,slices 实际被修改为0
 if (slicesString.equals(AbstractBulkByScrollRequest.AUTO_SLICES_VALUE)) {
            return AbstractBulkByScrollRequest.AUTO_SLICES;
        }
public static final int AUTO_SLICES = 0;
public static final String AUTO_SLICES_VALUE = "auto";

           

_reindex 中添加 slices,将会自动完成上面手动切片创建的请求;自动切片创建的子请求有些不一样的特征:

  1. 你可以使用 Tasks APIs 查看这些子请求,这些子请求是带有

    slices

    请求任务的”子”任务。
  2. 获取带有参数

    slices

    请求的任务状态,将只返回包含已完成切片的状态
  3. 可以分别对这些子请求,进行任务取消或者重新调节限速
  4. 重新调速带有

    slices

    参数的请求,将会按比例调速它的子任务。
  5. 取消带有

    slices

    参数的请求,将会取消它的所有子任务。
  6. 由于切片的性质,可能会每个切片的文档并不均匀,会出现某些切片某些切片可能比其他切片大;但是所有文档都会被划分到某个切片中。
  7. slices 请求如果含有

    requests_per_second

    max_docs

    ,将会按比例分配给每个子请求。结合上面关于分布不均匀的观点,将

    max_docs

    与切片一起使用可能会出现满足条件的

    max_docs

    文档不被重新索引。
  8. 尽管这些快照几乎都是在同一时间获取,但是每个子请求,可能获取的源快照会有稍微的不同。

合理选择切片数目

自动切片,设置

slices

auto

,将为大多数索引选择一个合理切片数目。如果手动切片或以其他方式调整自动切片,应当明白以下几个点:

  1. slices

    的数目等于索引的数目时,查询性能是最优的。设置

    slices

    高于分片数通常不会提高效率,反而会增加开销(CPU,磁盘 IO 等)。
  2. 索引性能会在可用资源与切片数之间线性地缩放
  3. 查询或索引性能在运行时是否占主导地位,取决于重新索引的文档和集群资源。

重新索引的路由

默认情况下,如果

_reindex

看到一个带有路由的文档,则路由将被保留,除非它被脚本更改。可以在

dest

的 JSON 体内上重新设置

routing

,从而改变之前的路由值,

routing

的可取值如下:

keep

keep

为默认值,将为每个匹配项发送的批量请求的路由,设置为匹配项旧的路由(就保持旧的路由方式)。

discard

将发送的批量请求的路由设置为

null

=

=

之后的值

示例,使用以下请求将

source_index

中公司名称为

cat

的所有文档复制到

source_index

且路由设置为

cat

POST _reindex
{
  "source": {
    "index": "source_index",
    "query": {
      "match": {
        "company": "cat"
      }
    }
  },
  "dest": {
    "index": "dest_index",
    "routing": "=cat"
  }
}           

默认情况下,

_reindex

使用滚动批处理

1000

。您可以使用元素中的

size

字段更改批处理大小:

POST _reindex
{
  "source": {
    "index": "source_index",
    "size": 100
  },
  "dest": {
    "index": "dest_index",
    "routing": "=cat"
  }
}           

重索引使用预处理 Pipeline

重索引也可以使用

ingest pipeline

的特性,来富化数据;示列如下:

POST _reindex
{
  "source": {
    "index": "source"
  },
  "dest": {
    "index": "dest",
     "pipeline": "some_ingest_pipeline" #提前定义的 pipeline
  }
}           

实战示例

基于查询重新索引文档

可以通过在

source

中添加查询条件,对有需要的文档进行重新索引;

例如,复制

user.id

值为

kimchy

文档到

my-new-index-000001

POST _reindex
{
  "source": {
    "index": "my-index-000001",
    "query": {
      "term": {
        "user.id": "kimchy"
      }
    }
  },
  "dest": {
    "index": "my-new-index-000001"
  }
}           

基于 max_docs 重新索引文档

通过在请求体中设置

max_docs

参数,控制重建索引的文档的个数。

例如:从

my-index-000001

复制一个文档到

my-new-index-000001

POST _reindex
{
  "max_docs": 1,
  "source": {
    "index": "my-index-000001"
  },
  "dest": {
    "index": "my-new-index-000001"
  }
}           

基于多源重新索引

source

index

属性值可以是一个 list;这样可以允许复制多个源的文档到目的数据流或索引,但是需要注意多个源的文档中字段的类型必须一致。

例如复制

my-index-000001

my-index-000002

索引的文档:

POST _reindex
{
  "source": {
    "index": ["my-index-000001", "my-index-000002"]
  },
  "dest": {
    "index": "my-new-index-000002"
  }
}           

选择字段重新索引

只重新索引每个文档筛选的字段;

例如,以下请求仅重新索引每个文档的

user.id

_doc

字段:

POST _reindex
{
  "source": {
    "index": "my-index-000001",
    "_source": ["user.id", "_doc"]
  },
  "dest": {
    "index": "my-new-index-000001"
  }
}           

通过重新索引修改文档中字段名字

_reindex

可用于复制源索引文档,在写入目的索引之前,重命名字段;假设

my-index-000001

索引有以下文档:

POST my-index-000001/_doc/1?refresh
{
  "text": "words words",
  "flag": "foo"
}           

但是你想把字段名

flag

替换成

tag

,处理手段如下(当然也可以用 ingest pipeline):

POST _reindex
{
  "source": {
    "index": "my-index-000001"
  },
  "dest": {
    "index": "my-new-index-000001"
  },
  "script": {
    "source": "ctx._source.tag = ctx._source.remove(\"flag\")"
  }
}           

现在获取新索引文档

GET my-new-index-000001/_doc/1           

返回值如下:

{
  "found": true,
  "_id": "1",
  "_index": "my-new-index-000001",
  "_type": "_doc",
  "_version": 1,
  "_seq_no": 44,
  "_primary_term": 1,
  "_source": {
    "text": "words words",
    "tag": "foo"
  }
}           

重新索引每日索引

_reindex

结合 Painless 脚本来重新索引每日索引,将新模板应用于现有文档。假设你有如下索引并包含下列文档

PUT metricbeat-2021.05.10/_doc/1?refresh
{"system.cpu.idle.pct": 0.908}

PUT metricbeat-2021.05.11/_doc/1?refresh
{"system.cpu.idle.pct": 0.105}           

通配

metricbeat-*

索引的新模板,已经加载到 Elasticsearch 中,但是该模板只会对新建的索引生效。Painless 可用于重新索引现有文档,并应用新模板。下面的脚本从索引名中提取日期,并创建一个新索引,新索引名添加 -1。

metricbeat-2021.05.10

所有的数据将会被重建到

metricbeat-2021.05.10-1

POST _reindex
{
  "source": {
    "index": "metricbeat-*"
  },
  "dest": {
    "index": "metricbeat"
  },
  "script": {
    "lang": "painless",
    "source": "ctx._index = 'metricbeat-' + (ctx._index.substring('metricbeat-'.length(), ctx._index.length())) + '-1'"
  }
}           

之前

metricbeat

索引的数据,都能从新的索引从获取到:

GET metricbeat-2021.05.10-1/_doc/1
GET metricbeat-2021.05.11-1/_doc/1           

提取源的随机子集

_reindex

可用于提取源的随机子集以进行测试:

POST _reindex
{
  "max_docs": 10,
  "source": {
    "index": "my-index-000001",
    "query": {
      "function_score" : {
        "random_score" : {},
        "min_score" : 0.9    #备注1
      }
    }
  },
  "dest": {
    "index": "my-new-index-000001"
  }
}           

可能需要根据从源中提取数据的相对数量,来调整

min_score

的值

重新索引时修改文档

_update_by_query

一样,

_reindex

支持使用 script 修改文档;不同的是,

_reindex

中使用脚本可以修改文档的元数据。

此示例增加了源文档的版本:

POST _reindex
{
  "source": {
    "index": "my-index-000001"
  },
  "dest": {
    "index": "my-new-index-000001",
    "version_type": "external"
  },
  "script": {
    "source": "if (ctx._source.foo == 'bar') {ctx._version++; ctx._source.remove('foo')}",
    "lang": "painless"
  }
}           

_update_by_query

一样,你可以设置

ctx.op

更改在

dest

上执行的操作:

noop

如果决定不必在目标中为文档重新索引,则需要在脚本中设置 ctx.op=“noop”。响应主体中的

noop

计数器将报告不做任何的操作。

delete

如果必须从目标(

dest

)中删除文档,则需要在脚本中设置 ctx.op=“delete”。删除将在响应正文中的已删除计数器中报告 。

ctx.op

为其他任何值都将返回错误,就像设置中的其他任何字段一样

ctx

同时还可以更改一些索引元信息,但是谨慎操作:

  • _id
  • _index
  • _version
  • _routing

如果将

_version

null

或将其从

ctx

映射中清除,就像不在索引请求中发送版本一样; 则无论目标上的版本或

_reindex

请求中使用的版本类型如何,都会导致目标中的文档被覆盖。

远程重新索引

重新索引支持从远程 Elasticsearch 复制数据:

POST _reindex
{
  "source": {
    "remote": {
      "host": "http://otherhost:9200",
      "username": "user",
      "password": "pass"
    },
    "index": "my-index-000001",
    "query": {
      "match": {
        "test": "data"
      }
    }
  },
  "dest": {
    "index": "my-new-index-000001"
  }
}           

Host 参数必须包含 scheme,host,port (如:

https://otherhost

:9200)或者代理路径(

:9200/proxy)。

_reindex 需要基本授权认证链接远程 Elasticsearch 集群,才需要用户名和密码参数;使用基本身份验证时请确保使用 协议,否则密码将以纯文本形式发送。

如果是 reindex 远程集群的数据,则必须在当前集群的某个节点(请求发送到的那个节点,即协调节点)配置白名单,在 elasticsearch.yml 文件中添加 reindex.remote.whitelist 属性,该属性的值为请求远程集群节点的 host:port,可以用逗号分隔配置多个,也可以使用通配符方式;

reindex.remote.whitelist: "otherhost:9200, another:9200, 127.0.10.*:9200, localhost:*"           

此外在做远程

reindex

时,需要注意集群之前的版本兼容问题;Elasticsearch 不支持跨大版本的向前兼容,如不能从 7.x 群集重新索引到 6.x 群集

从远程服务器重新索引时使用堆内缓冲区,默认最大为 100mb;如果远程索引的文档非常大,那么批的 size 就应该设置的小一点。

如下代码块设置 batch size 为10:

POST _reindex
{
  "source": {
    "remote": {
      "host": "http://otherhost:9200"
    },
    "index": "source",
    "size": 10,
    "query": {
      "match": {
        "test": "data"
      }
    }
  },
  "dest": {
    "index": "dest"
  }
}           

连接远程 Elasticsearch 集群,可以通过

socket_timeout

connect_timeout

,分别设置

socket

读取超时时间和链接超时时间,在一定程度上保证 Reindex 的稳定性(网络延迟问题),两者的默认值均为 30s。

如下示例分别设置

socket

读取超时为 1 分钟和连接超时时间 10s:

POST _reindex
{
  "source": {
    "remote": {
      "host": "http://otherhost:9200",
      "socket_timeout": "1m",
      "connect_timeout": "10s"
    },
    "index": "source",
    "query": {
      "match": {
        "test": "data"
      }
    }
  },
  "dest": {
    "index": "dest"
  }
}           

配置 SSL 参数

从远程集群

reindex

支持配置 ssl;这些参数是无法在

_reindex

请求体配置;必须在

elasticsearch.yml

文件中指定,但在 Elasticsearch 密钥库中添加的安全设置除外,可支持的 ssl 参数。

配置如下:

描述
reindex.ssl.certificate_authorities 应当信任的 PEM 编码证书文件的路径列表;但不能同时指定 reindex.ssl.certificate_authorities和 reindex.ssl.truststore.path
reindex.ssl.truststore.path 要信任的证书的 Java Keystore 文件的路径;该密钥库可以采用”JKS”或“PKCS#12”格式,但不能同时指定 reindex.ssl.certificate_authorities 和 reindex.ssl.truststore.path
reindex.ssl.truststore.password 信任库的密码(reindex.ssl.truststore.path)。此设置不能用于reindex.ssl.truststore.secure_password
reindex.ssl.truststore.secure_password 信任库的密码(reindex.ssl.truststore.path)。此设置不能用于reindex.ssl.truststore.password
reindex.ssl.truststore.type 信任库的类型(reindex.ssl.truststore.path)。必须为jks或PKCS12。如果信任库路径以“ .p12”,“.pfx”或“ pkcs12”结尾,则此设置默认为PKCS12。否则,默认为jks。
reindex.ssl.verification_mode 表示防止中间人攻击和证书伪造的验证类型。其中一个 full(验证主机名和证书路径), certificate (验证证书路径,而不是主机名)或none(不执行任何验证-这是在生产环境中强烈反对)。默认为 full
reindex.ssl.certificate 指定用于HTTP客户端身份验证的 PEM 编码证书(或证书链)的路径(如果远程集群需要)。此设置 reindex.ssl.key 还需要设置。您不能同时指定 reindex.ssl.certificate和reindex.ssl.keystore.path。
reindex.ssl.key 指定与用于客户端身份验证(reindex.ssl.certificate)的证书相关联的 PEM编码的私钥的路径。您不能同时指定reindex.ssl.key 和 reindex.ssl.keystore.path。
reindex.ssl.key_passphrase 指定用于 reindex.ssl.key 加密 PEM 编码的私钥(reindex.ssl.key)的密码。不能与一起使用reindex.ssl.secure_key_passphrase
reindex.ssl.secure_key_passphrase 指定用于 reindex.ssl.key 加密 PEM 编码的私钥(reindex.ssl.key)的密码。不能与一起使用reindex.ssl.key_passphrase
reindex.ssl.keystore.path 指定密钥库的路径,该密钥库包含用于HTTP客户端身份验证的私钥和证书(如果远程集群需要)。该密钥库可以采用“ JKS”或“ PKCS#12”格式。您不能同时指定 reindex.ssl.key 和 reindex.ssl.keystore.path
reindex.ssl.keystore.type 密钥库的类型(reindex.ssl.keystore.path)。必须为 jks 或 PKCS12。如果密钥库路径以“ .p12”,“.pfx” 或 “ pkcs12” 结尾,则此设置默认为 PKCS12。否则,默认为jks
reindex.ssl.keystore.password 密钥库(reindex.ssl.keystore.path)的密码。此设置不能用于reindex.ssl.keystore.secure_password
reindex.ssl.keystore.secure_password 密钥库(reindex.ssl.keystore.path)的密码。此设置不能用于reindex.ssl.keystore.password
reindex.ssl.keystore.key_password 密钥库(reindex.ssl.keystore.path)中密钥的密码。默认为密钥库密码。此设置不能用于 reindex.ssl.keystore.secure_key_password
reindex.ssl.keystore.secure_key_password 密钥库(reindex.ssl.keystore.path)中密钥的密码。默认为密钥库密码。此设置不能用于 reindex.ssl.keystore.key_password