Elasticsearch 迁移记录:从 7.14 到 8.x
为什么迁移?
公司当前业务场景有语义搜索的需求,具体实现方案是对输入的 query 进行 embedding 计算,并与索引中文档的 embedding 进行余弦相似度匹配,以实现相同语义内容的召回。当前使用的 Elasticsearch 版本为 7.14,对于向量的计算只能通过 function_script 的方式实现,这种方式需要遍历所有文档进行计算,效率极低,搜索耗时较高。而 Elasticsearch 8.x 版本支持对向量进行索引计算,大大优化了检索效率,因此升级至 8.x 版本势在必行。
迁移方案确定
在确定迁移方案时,我们考虑了以下几种方案:
-
Snapshot + COS
- 通过创建快照并将其存储在 COS(对象存储服务)中,然后在目标集群中恢复快照。
- 优点:简单,适合数据量较小的场景。
- 缺点:无法对索引结构进行升级,迁移后需要手动更新索引结构。
-
Logstash
- 使用 Logstash 进行数据的全量和增量迁移。
- 优点:可以在迁移过程中对数据进行处理和转换,适合数据量较大的场景。
- 缺点:配置较为复杂,迁移时间较长。
-
CCR(跨集群复制)
- 使用 Elasticsearch 的跨集群复制功能,将数据从源集群复制到目标集群。
- 优点:实时同步数据,迁移过程平滑。
- 缺点:需要源和目标集群能够通过内网互相访问,配置复杂。
在调研方案过程中,发现当前使用的 Elasticsearch 集群存在历史遗留问题:开发(dev)集群和生产(prod)集群使用同一个网段的 VPC,导致只有一个集群可以通过内网访问。实测中发现,prod 集群可以通过内网访问,而 dev 集群只能通过公网地址访问。由于网络配置无法变更,平滑的迁移方案都依赖内网打通才能进行,因此我们选择了以下迁移方案:
- Dev 环境:使用 Snapshot + COS 的方式进行有损迁移。
- Prod 环境:使用 Logstash 全量 + 增量的方式进行迁移。
Dev 迁移方案
创建 COS 桶快照仓库
首先,在 dev 环境中创建 COS 桶快照仓库:
PUT _snapshot/dev_cos_backup
{
"type": "cos",
"settings": {
"app_id": "130xxxx882",
"access_key_id": "AKIDiIxxxxxxxxgOs9E5g28zbxAC0",
"access_key_secret": "by691xxxxxxxxx9LJ2VinkSyFIE1av0",
"bucket": "es-snapshot",
"region": "na-siliconvalley",
"compress": true,
"chunk_size": "500mb",
"base_path": "dev_cos_backup/"
}
}
创建现有数据快照
PUT _snapshot/my_cos_backup/snapshot_dev
{
"indices": "index1,index2,..."
}
查询快照进度
GET _snapshot/my_cos_backup/snapshot_dev
在目标集群导入数据快照
POST _snapshot/my_cos_backup/snapshot_dev/_restore
切换新集群
该方案只能将数据原封不动地迁移过来,无法对索引结构进行升级,因此迁移完成后还需手动更新索引结构,以支持向量的快速召回。
Prod 迁移方案
使用 Logstash 全量 + 增量的方式
在迁移之前,可以在目标集群中先创建好索引结构的变更。需要指定输入和输出的 index,Logstash 不会自动创建 index。
全量迁移
input {
elasticsearch {
hosts => ["http://172.26.0.6:9200"]
index => "index"
user => "elastic"
password => "xxxxxxxxxx"
query => '{"query": {"match_all": {}}}'
size => 20
scroll => "1m"
docinfo => true
}
}
output {
elasticsearch {
hosts => ["http://172.18.6.39:9200"]
index => "index"
user => "elastic"
password => "xxxxxxxxxx"
document_id => "%{[@metadata][_id]}"
}
}
增量迁移
input {
elasticsearch {
hosts => ["http://172.26.0.6:9200"]
index => "index"
user => "elastic"
password => "xxxxxxxxxx"
query => '{
"query": {
"range": {
"created_at": {
"gte": "now-1h"
}
}
}
}'
schedule => "* * * * *"
docinfo => true
}
}
output {
elasticsearch {
hosts => ["http://172.18.6.39:9200"]
index => "index"
user => "elastic"
password => "xxxxxxxxxx"
document_id => "%{[@metadata][_id]}"
}
}
总结
通过以上方案,我们成功地将 Elasticsearch 从 7.14 版本迁移到了 8.x 版本。虽然在迁移过程中遇到了一些网络配置和历史遗留问题,但通过合理的方案选择和实施,我们最终实现了业务需求的优化和性能的提升。