为方便大家验证,这里给出 reindex github 源码地址。
https://github.com/elastic/elasticsearch/blob/001fcfb931454d760dbccff9f4d1b8d113f8708c/server/src/main/java/org/elasticsearch/index/reindex/ReindexRequest.java
reindex 常见问题:
reindex 操作的本质是从一个或多个源索引中读取文档,并将这些文档索引到一个目标索引中,可能还涉及对文档的某些转换。
以下是从源码中得出的 reindex 操作的关键点:
ReindexRequest 定义了源索引(从中读取文档)和目标索引(将文档索引到其中)。
可以为源索引定义一个查询(使用 setSourceQuery 方法),以确定哪些文档应该被重新索引。
也就是可以迁移满足给定检索语句的数据。
如果提供了一个脚本,它可以在文档从源索引移动到目标索引之前对文档进行修改或转换。
文档是批量从源索引读取并批量索引到目标索引的。
批处理的大小可以通过 setSourceBatchSize 方法进行调整。
这个值究竟可以多大,源码并没有明示。但是如下规则咱们得知道!
reindex 不仅可以在当前 Elasticsearch 集群中的索引之间移动文档(如图 1 所示),还可以从一个远程的 Elasticsearch 集群读取文档(如图 2 所示)。
这是通过 RemoteInfo 类实现的,它包含了远程集群的所有必要信息。
包含信息如下:
在执行 reindex 操作之前,会进行一系列的验证检查(使用 validate 方法),以确保请求是合法的。
ReindexRequest 类包含了将请求序列化到网络传输格式并从该格式反序列化的方法。
这允许 Elasticsearch 节点之间有效地通信并执行 reindex 请求。
ReindexRequest 可以被转化为一个描述性的字符串(使用 toString 方法)或一个XContent格式(通常是JSON,使用 toXContent 方法),这对于日志记录和调试非常有用。
总结起来,reindex 操作的本质是从源索引读取文档、可能进行一些转换,然后将这些文档索引到目标索引。
此操作可以在当前集群的索引之间进行,也可以跨集群进行。这是一种强大的方式,可以用于数据迁移、索引重组、数据转换等任务。
重新索引操作的速度受多个因素的影响, 如果希望加速 reindex 操作,以下是一些建议:
ReindexRequest 有一个 setSourceBatchSize 方法,允许我们设置每批处理的文档数量。
/**
* Sets the scroll size for setting how many documents are to be processed in one batch during reindex
*/
public ReindexRequest setSourceBatchSize(int size) {
this.getSearchRequest().source().size(size);
return this;
}
增加批次大小可能会提高性能,但请注意,太大的批次可能会导致内存问题或请求超时。
slice 在 Elasticsearch 的重索引操作中确实可以帮助提速。slice 是一种将大型查询分解为多个较小部分并并行执行它们的方法,从而使整体操作更快。
在 ReindexRequest 类中,我们可以看到方法 forSlice(TaskId slicingTask, SearchRequest slice, int totalSlices),它允许我们为给定的滚动请求创建一个子切片。
关于设置切片数量: 当我们执行重索引操作时,可以设置 slices 参数来指定我们想要的切片数。
例如,如果我们选择 slices: 5,那么 Elasticsearch 将尝试将查询拆分成5个子查询,并尽可能均匀地分布文档。
使用切片后,每个切片都可以在单独的线程或节点上并行执行。这样,如果我们有多个节点或足够的资源,切片可以显著提高重索引的速度。
实际命令:
在 Elasticsearch REST API 中,进行带切片的重索引操作的命令可能如下:
POST _reindex
{
"source": {
"index": "old_index",
"size": 1000,
"slice": {
"id": 0,
"max": 5
}
},
"dest": {
"index": "new_index"
}
}
在上面的命令中,我们将原始索引分成了5个切片,并使用 id 参数来指定当前切片的编号。
要并行执行所有切片,需要为每个切片编号运行此命令(在此例中,从0到4)。
虽然切片可以加速操作,但它也会增加集群的负担,因为每个切片都会创建自己的滚动上下文。确保的 Elasticsearch 集群有足够的资源来处理我们选择的切片数量。
切片操作的最佳数量取决于数据、查询和集群配置。可能需要进行一些性能测验来找到最佳的切片数量。
总的来说,slice 可以显著提高重索引操作的速度(一会我们验证一把,用事实证明),但需要确保正确使用它,以便在提高速度的同时不过度负担集群。
如果我们在 reindex 请求中使用了查询来筛选文档,确保该查询是优化的。避免使用复杂或低效的查询。比如:复杂嵌套查询、wildcard模糊查询等都尽量避免。
增加 Elasticsearch节点的 CPU、内存和I/O能力可以提高 reindex 的速度。
如果我们正在从远程集群进行重新索引,确保两个集群都有足够的资源。
这种针对数据量极大的情况。
在目标索引上临时禁用一些功能,如刷新和副本。完成 reindex 后,再启用它们:
设置 index.number_of_replicas
为 0 以禁用副本。
设置 index.refresh_interval
为 -1 以禁用刷新。
如果我们正在在 reindex 操作中使用脚本对文档进行转换,考虑使用 Ingest Pipelines,这可能比脚本更高效。
如果从远程集群重新索引,确保网络连接是高速、低延迟的。限制其他网络密集型操作的使用,以确保 reindex 请求可以充分利用带宽。
这属于边缘化建议,一般常识属于必知必会的。
尝试在集群的非高峰时段执行 reindex 操作,并限制执行其他资源密集型操作,如大型搜索或其他索引操作(如段合并等)。
确保没有任何插件或外部脚本影响 reindex 操作的性能。
使用Elasticsearch的监控工具,如 Elastic Stack 的监控功能,来监控 reindex 操作的性能。这可以帮助我们识别瓶颈并进行相应的调优。
考虑到这些建议,最好在生产环境中进行测试,以找到最佳的设置和优化策略。
需要一个大型索引,这样性能差异才会明显。小数据集可能不会显示出明显的差异。
确保 Elasticsearch 集群在开始测试之前是健康的,所有节点都是在线的,没有挂起的任务。
确保集群上没有其他大型查询或索引操作在运行,以免影响性能测试结果。
## 第一种:直接迁移。
"took": 4005,
POST _reindex
{
"source": {
"index": "image_index"
},
"dest": {
"index": "image_index_direct"
}
}
GET image_index_direct/_count
## 第二种,加了并行处理!
POST _reindex
{
"source": {
"index": "image_index",
"slice": {
"id": 0,
"max": 5
}
},
"dest": {
"index": "image_index_slice"
}
}
比较两次重索引的总时间。理论上,使用 slice 的版本应该更快,尤其是在有多个节点和大量数据的集群中。
如下视频所示,我优先小范围做了验证。
数据量 16MB,上万条数据迁移结果对比:
迁移方式 | 耗时 |
---|---|
直接迁移 | 4005ms |
slice迁移 | 1123ms |
数据量 112MB,15万条长津湖影评数据迁移结果对比:
迁移方式 | 耗时 |
---|---|
直接迁移 | 30000ms左右(事后视频回放看到的) |
slice迁移 | 10263ms |
综上两种数量级不同数据的 reindex 结果可以看出,加了 slice 能提速 3-4倍!
更多节点规模集群和大规模数据,期待大家留言反馈结果。
有了方案,更多的付诸实践,拿出结果才更有谁服力!
加油!
本文分享自 铭毅天下Elasticsearch 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!