ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

ES 7.17.9 到 OpenSearch 3.4.0 迁移实战:Docker 模拟与 routing 修复

ES 7.17.9 到 OpenSearch 3.4.0 迁移实战:Docker 模拟与 routing 修复 最近在帮团队做一套测试环境的中间件替换核心任务是把 Elasticsearch 7.17.9 里的业务数据迁移到 OpenSearch 3.4.0整个过程在 Windows 11 上用 Docker Desktop 容器化模拟完成。迁移本身并不复杂但当你真正动手做的时候版本差异、索引映射、routing 策略、异步写入逻辑这些细节会一个接一个地冒出来。这篇文章我把完整的操作路径、方案选型和踩坑记录写下来给准备从 ES 迁移到 OpenSearch 的团队一个可复用的参考流程。1. 迁移背景与方案选型思路1.1 为什么选 ES 7.17.9 和 OpenSearch 3.4.0 这对组合Elasticsearch 和 OpenSearch 的渊源在圈子里基本是公开背景了OpenSearch 是从 Elasticsearch 7.10.2 fork 出来的开源分支之后两边各自独立演进。实际项目里我们源端用的是 7.17.9这是 Elasticsearch 在 7.x 后期一个比较稳的版本也是不少公司在许可变更前最后一批能低成本平滑评估的版本之一。目标端选择 OpenSearch 3.4.0则是客户侧对未来兼容性的硬性要求。这里有个非常关键的认知OpenSearch 3.4.0 和 ES 7.17.9 的底层 Lucene 版本、索引段格式、部分 DSL 解析逻辑并不完全一致所以你不能想当然地认为“ES 的索引目录拷贝过去就能直接用”。跨大版本的数据迁移必须经过逻辑层导出再导入或者借助专门的数据迁移工具而不是直接搬文件。这也是为什么我坚持用 Docker Desktop 来模拟整套迁移。本地起容器有几个现实好处一是环境隔离干净不会污染你本机已经装好的 ES 或其他中间件二是资源可控Docker Desktop 可以随时调内存和 CPU 配额模拟生产节点配置很方便三是实验成本低迁移出问题直接删容器重建连数据卷一起清理不用在物理机上反复折腾。对团队里第一次接触 ES 到 OpenSearch 迁移的人来说这种做法最直观也最容易复现。1.2 版本兼容性评估是第一步别一上来就导数据很多新手拿到迁移任务后第一反应是找工具开干我建议先花半天做版本兼容性评估。结合 ES 7.17.9 到 OpenSearch 3.4.0 的场景主要看四件事评估维度ES 7.17.9 侧表现OpenSearch 3.4.0 侧表现结论REST API 兼容性_search、_bulk、_mapping等 REST 接口大部分 REST API 兼容基础 API 可直接复用索引映射类型text、keyword、nested、geo_point 等支持相同字段类型但部分参数默认值不同映射需要逐字段核对索引生命周期管理ILM 策略ISM 策略API 名称和配置结构不同需要新建策略并绑定索引安全认证xpack.security内置安全插件默认开启需显式关闭或改造容器模拟时建议先关闭我当时还把 ES 侧生产环境里所有索引的_settings和_mappings全部拉出来在 OpenSearch 里逐项对照发现有几个索引用了自定义 normalizer还有两个索引有 nested 字段。这些内容在迁移时必须保留在目标索引的 mapping 里否则数据导入后查询行为会变。Docker Desktop 模拟阶段如果不先做这步评估后面导数据、校验、切流的时候大概率会返工。2. 环境准备用 Docker Desktop 搭起 ES、Kibana 和 OpenSearch2.1 Windows 11 下 Docker Desktop 的安装与配置要点先把宿主环境跑起来。我是 Windows 11 WSL2 的组合Docker Desktop 4.x 对 WSL2 后端支持很成熟内存和 CPU 默认配置对跑 3-4 个容器来说通常够用但迁移场景建议把内存配额调到 8GB 以上。可以在.wslconfig里这样写[wsl2] memory8GB processors4 swap2GB如果你本机还没装过 ES想先验证 Docker 环境是否正常最直接的方式是拉一个 ES 镜像并启动容器映射宿主机端口后访问http://localhost:9200能返回带cluster_name的 JSON 说明容器运行正常。如果要确认 Windows 上是否已经装了 ES则直接看服务列表或者9200端口是否被监听即可。Docker Desktop 安装完成后建议确认一下镜像源配置。国内网络环境下拉取 Docker Hub 镜像偶尔会卡住我一般习惯在 Docker Desktop 的 Settings 里配置一个可用的 registry mirror这样后续拉elasticsearch、kibana、opensearch镜像会快很多。这个细节在“dockerdesktop cn”社区里也常被讨论实际体验差别很大。2.2 用 Docker Compose 编排三套服务的容器架构迁移模拟环境我用 Docker Compose 一次性编排四个服务源端 ES 7.17.9、源端 Kibana 7.17.9、目标端 OpenSearch 3.4.0、目标端 OpenSearch Dashboards 3.4.0。写一个docker-compose.yml直接在项目根目录跑docker compose up -d即可。version: 3.8 services: es: image: docker.elastic.co/elasticsearch/elasticsearch:7.17.9 container_name: es-migration environment: - discovery.typesingle-node - xpack.security.enabledfalse - ES_JAVA_OPTS-Xms1g -Xmx1g ports: - 9200:9200 volumes: - es-data:/usr/share/elasticsearch/data networks: - migration-net kibana: image: docker.elastic.co/kibana/kibana:7.17.9 container_name: kibana-migration depends_on: - es environment: - ELASTICSEARCH_HOSTShttp://es:9200 ports: - 5601:5601 networks: - migration-net opensearch: image: opensearchproject/opensearch:3.4.0 container_name: opensearch-target environment: - discovery.typesingle-node - plugins.security.disabledtrue - OPENSEARCH_JAVA_OPTS-Xms1g -Xmx1g ports: - 9201:9200 volumes: - opensearch-data:/usr/share/opensearch/data networks: - migration-net opensearch-dashboards: image: opensearchproject/opensearch-dashboards:3.4.0 container_name: dashboards-target depends_on: - opensearch environment: - OPENSEARCH_HOSTShttp://opensearch:9200 - DISABLE_SECURITY_DASHBOARDS_PLUGINtrue ports: - 5602:5601 networks: - migration-net volumes: es-data: opensearch-data: networks: migration-net: driver: bridge这里有几个容易踩的细节。第一OpenSearch 和 ES 默认都监听容器内9200所以宿主机端口一个映射9200ES、一个映射9201OpenSearch避免互相抢占。第二OpenSearch 3.4.0 镜像默认开启安全插件单节点模拟环境直接设plugins.security.disabledtrue可以省掉证书和账号配置的麻烦同时 Dashboards 也要配套设DISABLE_SECURITY_DASHBOARDS_PLUGINtrue否则访问 Dashboards 时会一直卡在登录页。第三Kibana 7.17.9 的目标连接地址是服务名es生产环境换成内网 IP 即可。容器都启动后先做健康检查docker compose ps curl http://localhost:9200/_cluster/health curl http://localhost:9201/_cluster/health两个接口都返回status:green或status:yellow说明迁移环境已经就绪。如果返回 red多半是磁盘或内存分配问题先看docker logs 容器名再排查。2.3 本地没有 Docker Desktop 时的备选路径顺带提一句“es 本地如何安装”这个问题。如果机器上没有 Docker Desktop也可以直接在 Windows 11 上下载 ES 和 Kibana 的压缩包通过bin/elasticsearch.bat和bin/kibana.bat启动配置config/elasticsearch.yml里的network.host和discovery.type: single-node。这种方式更轻量但环境复用性差尤其在多版本切换时容易冲突。我个人的建议是如果是临时验证功能直接压缩包方式如果要做完整迁移演练一步到位用 Docker Compose。3. 数据迁移路线三种方案怎么选3.1 快照恢复、dump 逻辑迁移、自研脚本的对比迁移 ES 数据到 OpenSearch社区里主流是三条路线目标都是把数据从一个集群搬到另一个集群风险和适用场景完全不同。方案原理优点缺点适用场景快照恢复底层 Lucene 索引文件级复制速度快接近原样跨大版本可能不兼容依赖源集群生成快照的基础路径同版本间复制或目标端 Lucene 完全兼容dump 逻辑迁移通过 Scroll API 查询原索引并导出 JSON 再导入跨版本友好兼容新老字段可挑选索引速度比快照慢routing 可能丢失需要额外处理ES 7.x → OpenSearch 3.x 这类跨大版本场景自研脚本封装 Scroll 查询 Bulk 异步写入可控性最强可自定义 routing 和字段映射开发量大需要处理分页、限流、异常重试数据量巨大或 mapping 极复杂时我最终选了 dump 逻辑迁移核心原因很简单源端 ES 7.17.9 和目标端 OpenSearch 3.4.0 的底层索引段格式有差异快照恢复不可靠。虽然 OpenSearch 官方提供了升级工具但跨多个版本的逻辑层迁移仍然以数据重放为主。而且逻辑迁移可以在导入前对字段做一次“翻译”比如源端有些 custom analyzer 在 OpenSearch 里不存在时可以提前在 mapping 阶段替换为等效配置这是快照方案做不到的。3.2 逻辑迁移中必须提前考虑的两个问题routing 和异步写入为什么单独把 routing 拎出来讲因为很多团队迁移完发现数据条数对得上但集群查询性能和分片分布完全变了十有八九是 routing 丢了。ES 的_routing字段决定文档写入哪个分片。比如订单索引按user_id做 routing同一用户的订单会落到同一分片查询时只要带上routinguser_A就能把查询请求路由到单个分片否则必须广播到所有分片。在 dump 逻辑迁移中默认的数据导出结果里没有保留文档写入时的_routing值——这个问题我在第 4 章实测部分会演示解决方式。异步写入则是另一个容易在迁移脚本里被忽略的点。互联网搜索热词里的“es 异步写入 java”对应的是 ES Java High Level REST Client 的 BulkProcessor 机制。实际生产里很多业务系统就是用异步批量写入来提升吞吐量的迁移数据到 OpenSearch 之后Java 客户端连接方式也要跟着切换老代码里org.elasticsearch.client.RestHighLevelClient需要换成org.opensearch.client.opensearch.OpenSearchClient或兼容迁移包。这是迁移流程里最容易被业务方遗漏的改造项。4. 实操开始从 ES 7.17.9 导出索引数据4.1 造一份能覆盖典型业务的测试数据模拟环境里我先建一个订单索引user_orders故意让它的字段覆盖 keyword、text、nested、geo_point、date 这些常见类型并且开启_routing.required按照user_id路由。这样迁移时才能暴露大多数字段和 routing 问题。PUT /user_orders { settings: { number_of_shards: 3, number_of_replicas: 1, analysis: { normalizer: { keyword_lower: { type: custom, filter: [lowercase] } } } }, mappings: { _routing: { required: true }, properties: { order_id: { type: keyword }, user_id: { type: keyword }, order_status: { type: keyword, normalizer: keyword_lower }, pay_amount: { type: double }, pay_time: { type: date, format: yyyy-MM-dd HH:mm:ss||epoch_millis }, items: { type: nested, properties: { sku: { type: keyword }, qty: { type: integer }, price: { type: double } } }, geo_point: { type: geo_point } } } }写入几条带 routing 的文档模拟真实业务写入方式curl -X PUT http://localhost:9200/user_orders/_doc/1001?routinguser_A -H Content-Type: application/json -d { order_id: 1001, user_id: user_A, order_status: paid, pay_amount: 259.00, pay_time: 2025-05-01 12:30:00, items: [ { sku: sku-001, qty: 2, price: 88.00 }, { sku: sku-002, qty: 1, price: 83.00 } ], geo_point: 31.23,121.47 } 再写入十几条不同user_id的订单方便后面校验条数和抽样对比。写完以后用curl http://localhost:9200/user_orders/_count确认总数。4.2 用 elasticdump 导出 mapping 和 data我这里用的工具是elasticdump它是 Node.js 生态里很常见的 ES 数据迁移工具npm 安装后可以直接用 npx 调用不需要额外起服务。导出分两步先导 mapping再导数据。在项目目录里建一个data目录用于挂载或落盘执行npx elasticdump \ --inputhttp://localhost:9200/user_orders \ --output/data/user_orders_mapping.json \ --typemapping npx elasticdump \ --inputhttp://localhost:9200/user_orders \ --output/data/user_orders_data.json \ --typedata \ --limit10000 \ --scroll-time10m说明几个参数。--limit10000控制 Scroll 每批次拉取 1 万条文档不是总数上限--scroll-time10m设置 Scroll 上下文保留 10 分钟数据量大的索引建议调大到 20m 或 30m否则 Scroll 上下文过期会报错。导出完成后看一眼输出文件的大小如果只有几十 KB 而源索引有大量数据大概率是--limit理解错了或者映射里某些字段导致序列化异常。4.3 导出过程中最容易翻车的三个点第一分页方式不是 page from/size。elasticdump 默认走 Scroll API它维护的是快照一致性视图导出期间源 ES 如果有新数据写入导出结果不会包含这些增量。这个特性并不算 bug但会让你在迁移校验时对不上数。我当时是先停业务写 10 分钟再做导出保证源端数据静止。第二routing 不会自动带出来。前面已经反复强调过elasticdump 导出的 data JSON 文件里只有_index、_id、_source这些字段没有_routing。如果你的业务强依赖 routing导出后必须单独做 routing 映射表或者干脆走自研脚本。为了演示我额外用 ES 的_search按user_id分组导出一份routing_key映射实际上生产上更好的做法是在源文档里冗余一个routing_key字段。第三大字段和高基数字段可能导致内存压力。source 里如果存了超大对象--limit10000会让导出进程内存飙升。遇到这种索引我建议把--limit降到 1000 或 2000宁可慢一点。还有_source里嵌套对象极深时JSON 序列化可能把堆内存打满可以配合--input-http-body {query:{bool:{filter:[{range:{pay_time:{gte:2025-01-01}}}]}}}做增量范围导出分批处理。5. 实操继续导入 OpenSearch 3.4.0 并做数据校验5.1 在 OpenSearch 里创建目标索引保留原 mapping目标端不是直接拿 elasticdump 往 OpenSearch 里灌数据而是先建索引再导数据。这里最关键的是目标 mapping 要和源 mapping 保持一致至少字段类型和 analyzer/normalizer 要一致。直接用刚才导出的user_orders_mapping.json导入npx elasticdump \ --input/data/user_orders_mapping.json \ --outputhttp://localhost:9201/user_orders \ --typemappingelasticdump 的--typemapping会把源 mapping 整包 POST 到目标索引OpenSearch 3.4.0 对_routing: {required: true}这类映射是兼容的。但如果你的源索引里有自定义分词器插件比如 IK 或 smartcnOpenSearch 3.x 的对应插件分支如果不匹配mapping 上传会直接报错。遇到这种情况我建议先在 OpenSearch 端安装同分支的 analysis 插件再执行 mapping 导入。上传成功后验证一下curl http://localhost:9201/user_orders/_mapping?pretty确认order_status字段的 normalizer 是否保留items字段是否还是 nested 类型。OpenSearch 3.4.0 对部分 ES 7.17 的 mapping 参数做了更严格的校验如果导完发现某个字段类型变成object而不是nested就要回头检查源 mapping 的定义。5.2 修正 routing 丢失问题用自定义 NDJSON 批量导入我不建议直接拿 elasticdump 的 data JSON 灌入 OpenSearch因为那样 routing 会丢。生产环境更稳妥的方式是写一个 Python 小脚本把 elasticdump 导出的 JSON 转换成保留了 routing 元数据的 NDJSON 格式再走_bulk接口导入。转换脚本的思路很简单逐行读取 elasticdump 导出文件把_source.user_id作为 routing 值写到 bulk action 的routing字段里。import json import sys if len(sys.argv) 3: print(用法: python rebuild_routing.py input.json output.ndjson) sys.exit(1) input_file sys.argv[1] output_file sys.argv[2] with open(input_file, r, encodingutf-8) as fin, \ open(output_file, w, encodingutf-8) as fout: for line in fin: obj json.loads(line) source obj.get(_source, {}) routing_key source.get(user_id, _no_routing) action { index: { _index: obj.get(_index, user_orders), _id: obj.get(_id), routing: routing_key } } fout.write(json.dumps(action, ensure_asciiFalse) \n) fout.write(json.dumps(source, ensure_asciiFalse) \n) print(转换完成共生成 {} 行 NDJSON.format(sum(1 for _ in open(output_file, r, encodingutf-8)) // 2))然后通过_bulk导入curl -X POST http://localhost:9201/_bulk \ -H Content-Type: application/x-ndjson \ --data-binary /data/user_orders_ndjson.ndjson如果你数据量很大建议分批导入比如每 5000 个 bulk action 一批。导入过程中可以通过_cat/indices观察文档数增长。如果只是想快速验证数据形状也可以直接跑npx elasticdump \ --input/data/user_orders_data.json \ --outputhttp://localhost:9201/user_orders \ --typedata \ --bulk-size5000这种方式的优点是省事缺点就是 routing 丢。所以最终采用哪个取决于你的业务对 routing 的敏感度。5.3 数据校验不能只比对条数要抽样比对字段内容导入完成后至少做三层校验。第一层是计数校验curl -s http://localhost:9200/user_orders/_count curl -s http://localhost:9201/user_orders/_count第二层是主链字段抽检比如取几个已知order_id在源和目标端分别查同一文档比对pay_amount、pay_time和order_status是否一致。第三层是对随机抽样文档做字段哈希比对。我通常写一个简单的 Python 或 Java 脚本从两个集群各取 1000 条文档的相同_id对_sourceJSON 做 MD5比对哈希是否一致。这一步能发现 mapping 变化导致的数据类型漂移比如 integer 被识别成 long或 double 被转了 float都可能造成值不一致。6. 业务侧切换Kibana 和 Java 客户端该怎么做6.1 Kibana 7.17.9 不能直接连 OpenSearch需要切换到 Dashboards这里有个很多团队会踩的坑Kibana 和 Elasticsearch 是一对绑定关系Kibana 7.17.9 无法直接连接 OpenSearch 3.4.0。Kibana 内部依赖了大量 ES 专有 APIOpenSearch 从 2.x 开始就没有兼容这套接口所以必须用 OpenSearch 官方配套的 OpenSearch Dashboards。我在 Compose 编排里已经加了一个opensearch-dashboards服务访问地址是http://localhost:5602。启动后第一件事是创建 Index Pattern把user_orders索引接进去。如果之前在 Kibana 里做了可视化 Dashboard迁移到 Dashboards 后需要逐项重建不要指望旧图能自动迁移。6.2 DSL 和索引生命周期管理的差异比想象中多大部分基础查询 DSL 在 OpenSearch 3.4.0 里是兼容的比如term、match、range、bool。但有一些运维层面的 API 完全不同最典型的是索引生命周期管理ES 侧叫 ILM调用_ilm/policyOpenSearch 侧叫 ISM调用_plugins/_ism/policies。迁移期间如果业务在 ES 里订了自动滚动策略必须在 OpenSearch 里重新建 ISM policy并把索引别名绑定到策略上。另一个差异是_cat/indices的返回格式里OpenSearch 会新增一些健康状态和段信息列脚本化对接时要注意字段次序不能按 ES 7.17 的某个固定列号解析。6.3 Java 客户端升级从异步 Bulk 到 OpenSearch Client热搜词里反复出现“es 异步写入 java”我多说几句。很多 Java 团队在 ES 时代用的是RestHighLevelClientBulkProcessor异步提交这套代码在 OpenSearch 3.4.0 时代不能直接搬。正确做法是引入org.opensearch.client:opensearch-java和org.opensearch.client:opensearch-rest-client然后用 Bulk 异步处理器重写写入逻辑。核心点有两个。第一客户端版本要和 OpenSearch 服务端版本对应3.4.0 对应的 Java 客户端用 3.4.x 的 release第二原来BulkRequest的构造方式有变化OpenSearch Java Client 使用流式 builder同时保留了_bulk底层协议所以性能不会有明显损失。迁移验证阶段可以先用一个小流量接口做灰度观察写入延迟和吞吐对比之后再全量切。BulkRequest bulkRequest new BulkRequest.Builder() .operations( Collections.singletonList( BulkOperation.of(o - o .index(IndexOperation.of(io - io .index(user_orders) .id(orderId) .routing(userId) .document(source))) ) ) ) .refresh(Refresh.True) .build(); client.bulk(bulkRequest);这个片段很容易误解为单条写入生产环境建议还是用 BulkProcessor 或分批构造ListBulkOperation一次提交几千条效果完全不一样。7. Docker Desktop 模拟环境中的高频坑与排查技巧7.1 容器 OOM 或 ES/OpenSearch 进程被系统杀掉Docker Desktop 模式下最常遇到的就是 OOM。ES 7.17.9 和 OpenSearch 3.4.0 的 JVM 堆默认会按照容器内存占比自动计算但如果 Docker Desktop 只给 WSL2 分配了 4GB 内存两个容器同时跑某个节点的进程很快会被操作系统杀掉。日志里会出现Native memory allocation (mmap) failed这类报错。现象常见原因处理方式容器一直重启JVM heap 过大或宿主机内存不足降低ES_JAVA_OPTS和OPENSEARCH_JAVA_OPTS到 512m 或 1g启动后_cluster/health是 red磁盘空间不足清理 Docker 卷或扩 WSL2 虚拟磁盘集群状态黄且分片未分配单节点副本数大于可用节点数设置number_of_replicas: 0或调为 1我实测下来模拟环境用 1g heap 单分片 副本 0 是最稳妥的组合既保证迁移可用又不至于把 Docker Desktop 拖垮。7.2 端口占用和跨容器访问问题Windows 宿主机上如果已经装了本机 ES9200端口就会冲突。排查方法很简单用netstat -ano | findstr :9200查看占用进程并决定结束它还是把容器端口改成别的。跨容器访问的问题则通常出在 Compose 网络配置上我的建议是服务间互相访问时使用 Compose 的服务名而不是localhost服务对宿主机暴露时才用http://localhost:9201。7.3 OpenSearch 安全插件导致的 401 和 SSL 握手失败我上手第一天就被 OpenSearch 3.4.0 默认开启的安全插件坑了一次。直接在 Compose 里设plugins.security.disabledtrue是最快的降级方式但如果你真的想体验带安全认证的迁移流程需要注意 SSL 证书验证会和 elasticdump 相互冲突。elasticdump 不支持直接跳过 SSL 验证需要配置--input-http-headers或--output-http-headers同时把证书导入 Node 的 CA 链里。模拟环境用关闭安全插件的方式更省事生产环境则建议保留安全插件并用账号密码走 HTTP 基础认证。7.4 镜像下载慢或 Docker Desktop 拉取失败这个问题在不同网络环境下体会完全不同。“dockerdesktop 使用教程”里经常提到配置 registry mirror我自己的经验是可以配一个然后重启 Docker Desktop 让配置生效。如果拉取还是失败检查docker images是不是已经有同 tag 的残留镜像删掉再拉。拉取opensearchproject/opensearch:3.4.0时偶尔会遇到 manifest 列表解析慢的情况重试一到两次基本能解决。7.5 导入速度太慢索引状态一直 yellow先确认是不是分片副本导致的集群状态问题。单节点模拟下如果源索引的number_of_replicas是 1导入 OpenSearch 后副本分片会一直 UNASSIGNED因为只有一个节点放不下主备两份。把副本改成 0 后状态会恢复 yellow 或 green。导入速度变慢则多半是 bulk size 没调好。elasticdump 的默认--bulk-size是 5000如果你的文档体积大5000 条 NDJSON 可能超过单个 bulk 请求的体量限制HTTP 会返回 413此时降为 1000 到 2000 反而更稳定。7.6 常用排查命令速查表命令作用docker compose ps查看四个容器运行状态docker logs es-migration -f查看 ES 实时日志docker logs opensearch-target -f查看 OpenSearch 实时日志curl localhost:9200/_cat/health查看 ES 集群健康状态curl localhost:9201/_cat/health查看 OpenSearch 集群健康状态curl localhost:9201/_cat/allocation/explain查看未分配分片原因curl localhost:9201/_nodes/stats查看节点 JVM 和堆内存使用这套命令如果能熟练用起来Docker Desktop 里 90% 的启动类和资源类问题都可以快速定位。8. 最后分享几个我在实际迁移中的经验技巧整个流程走完最深的体会就是数据迁移工具只是搬运工真正决定成败的是细节设计。我之前也遇到过直接把 elasticdump 数据文件灌进目标索引就跑的团队结果业务上线后查询限流一查 routing 全丢了索引分片热点极其严重。所以用 Docker Desktop 模拟迁移这个步骤非常有价值——它能让你在零成本环境里把所有细节走一遍而不是把生产环境当成试验场。再补两个实用技巧。第一个是迁移前在源端索引里加一个migration_flag字段标记写入时间迁移后用_search按时间范围拉取对比比单纯数条数可靠得多。第二个是如果数据量很大建议按索引拆分导出而不是把所有索引一次性处理这样单个索引出错时不会影响全局流程。我后续还会把这次迁移的脚本整理成工具化配置以后遇到类似 ES 7.x 到 OpenSearch 3.x 的项目能直接复用这套 Compose 和路由重建脚本几分钟就能完成一次完整演练。
返回列表