Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

跨集群迁移索引数据不一致 #80

Open
lianmeng0 opened this issue Oct 19, 2023 · 22 comments
Open

跨集群迁移索引数据不一致 #80

lianmeng0 opened this issue Oct 19, 2023 · 22 comments

Comments

@lianmeng0
Copy link

从集群5.6.4迁移索引到7.17.4,迁移界面是成功的,数据也是全部写入了,但是在7.17.4集群查询时,发现文档数不一致。ESM使用的是0.6.1版本。但是当多次运行迁移程序后,数据可以成功补全。
image
第一次迁移:
image
image
多次迁移后:
image
image

请问是怎么回事儿?还请指教。谢谢!

@medcl
Copy link
Owner

medcl commented Oct 31, 2023

查看之前,有手动刷新么?

@lianmeng0
Copy link
Author

lianmeng0 commented Nov 1, 2023 via email

@medcl
Copy link
Owner

medcl commented Nov 1, 2023

应该是 bulk 请求的部分文档失败了,esm 没有处理 429 的情况。体积一般是需要合并,或者和 mapping 有关系。

@fishjam
Copy link

fishjam commented Jan 2, 2024

我加入了 SortField, TruncateOutFile, SkipFields 等配置信息, 可以通过导出到本地文件的方式进行比较.
而且似乎代码中以前使用 fasthttp 等 http 库似乎有问题, 我简单的想通过 --regenerate_id --repeat_times=10 来生成测试数据也不行. 而更改 http 使用方式后自己就好了(我没有改这部分的实现). 这些一起体现在 #84 里.

示例:

   esm --sort=_id --source=http://localhost:9200 --src_indexes=bank --truncate_output --skip=_index --output_file=src.json
   esm --sort=_id --source=http://localhost:9200 --src_indexes=bank_sync --truncate_output --skip=_index --output_file=dst.json
   diff -W 200 -ry --suppress-common-lines src.json dst.json

@medcl
Copy link
Owner

medcl commented Jan 5, 2024

如果是为了生成测试数据,可以使用 Loadgen 来做:https://infinilabs.com/docs/latest/gateway/getting-started/benchmark/

@lianmeng0
Copy link
Author

你好!那该如何解决或者去避免 bulk 请求的部分文档失败?现有跨集群迁移索引,相同模板中的索引,小索引可以正常迁移,但是大索引却发现文档数相差太大。
小索引:
企业微信截图_20240318145932

大索引:
企业微信截图_20240318150206

@medcl
Copy link
Owner

medcl commented Mar 18, 2024

@lianmeng0 如果是因为 429 部分失败,可以尝试避免产生太大的压力,尽管迁移速度会慢一些,但是不会失败。
本工具只适合小规模迁移,比较复杂的数据迁移,可能需要完整的解决方案,极限网关的迁移功能处理了 bulk 的返回处理,可以试试

@lianmeng0
Copy link
Author

lianmeng0 commented Mar 18, 2024 via email

@fishjam
Copy link

fishjam commented Mar 19, 2024

个人建议:

  1. 尝试使用 --output_file + --fields 的功能, 将所有 records 的 id 等特殊字段导出到文件, 然后通过 diff/Beyond Compare 等工具比较到底是哪些记录没有被同步.
  2. 然后通过 --source_proxy 和 --dest_proxy= 指定本地的 fiddler 等工具抓包; 通过 --query 指定没有同步的数据 , 然后通过 fiddler, 日志 等查看出错的原因.

然后将使用的 esm版本 + 详细命令 + fiddler + 日志等 贴上来. 帮着分析是代码的问题还是使用方式的问题.

另外, 可以试试 v0.7.0 版本中提供的 --sync 功能. 我用之前的版本同步, 也发现有数据丢失的现象. 重构代码后, 再也没有发现丢失数据的现象.

@lianmeng0
Copy link
Author

lianmeng0 commented Mar 19, 2024

个人建议:

  1. 尝试使用 --output_file + --fields 的功能, 将所有 records 的 id 等特殊字段导出到文件, 然后通过 diff/Beyond Compare 等工具比较到底是哪些记录没有被同步.
  2. 然后通过 --source_proxy 和 --dest_proxy= 指定本地的 fiddler 等工具抓包;通过 --query 指定没有同步的数据 , 然后通过 fiddler, 日志 等查看出错的原因.

然后将使用的 esm版本 + 详细命令 + fiddler + 日志等 贴上来.帮着分析是代码的问题还是使用方式的问题.

另外, 可以试试 v0.7.0 版本中提供的 --sync 功能.我用之前的版本同步, 也发现有数据丢失的现象.重构代码后, 再也没有发现丢失数据的现象.

使用新版本后,发现不能够跨版本迁移
使用命令:/usr/local/esm/bin/esm -s http://10.10.8.50:9201 -x umedia_correction_sd_www_202212 -d http://10.10.7.51:8201 -y umedia_correction_sd_www_202212 -w 10 -b 20 -u "_doc" -c 5000 --sliced_scroll_size=10 --buffer_count=50000 -t 180m --refresh

返回报错:
[03-19 18:35:53] [INF] [ migrator.go:115 ,ParseEsApi] source es version: 5.6.4
[03-19 18:35:53] [ERR] [ v5.go:75 ,NewScroll] server error: {"error":{"root_cause":[{"type":"illegal_argument_exception","reason":"Fielddata access on the _uid field is disallowed"}],"type":"search_phase_execution_exception","reason":"all shards failed","phase":"query","grouped":true,"failed_shards":[{"shard":0,"index":"umedia_correction_sd_www_202212","node":"lmCdTd3aRESZwTswuGtfcQ","reason":{"type":"illegal_argument_exception","reason":"Fielddata access on the _uid field is disallowed"}}]},"status":400}
[03-19 18:35:53] [ERR] [ main.go:144 ,main] server error: {"error":{"root_cause":[{"type":"illegal_argument_exception","reason":"Fielddata access on the _uid field is disallowed"}],"type":"search_phase_execution_exception","reason":"all shards failed","phase":"query","grouped":true,"failed_shards":[{"shard":0,"index":"umedia_correction_sd_www_202212","node":"lmCdTd3aRESZwTswuGtfcQ","reason":{"type":"illegal_argument_exception","reason":"Fielddata access on the _uid field is disallowed"}}]},"status":400}

@fishjam
Copy link

fishjam commented Mar 20, 2024

看起来是类似 https://stackoverflow.com/questions/45427887/how-to-get-the-maximum-id-value-in-elasticsearch 的原因.
因为 --sync 功能需要排序, 所以默认采用了 _id(我只通过 docker 尝试并验证了 6.x 及以后的版本, 确实没有测试 5.x 版本) ,
你可以尝试加入 --sort= ( 表示不指定排序字段 ), 应该可以规避这个问题.

如果想使用 --sync 功能的话, 必须指定排序字段. 如果你的 src/dst 数据中有唯一可以排序的字段(比如你们自己的业务 id), 可以尝试以下命令(最好先在一些不重要的 index 上测试):

/usr/local/esm/bin/esm --sync --sort="你的业务ID" -s http://10.10.8.50:9201 -x umedia_correction_sd_www_202212 
  -d http://10.10.7.51:8201 -y umedia_correction_sd_www_202212 -u "_doc"

@lianmeng0
Copy link
Author

看起来是类似 https://stackoverflow.com/questions/45427887/how-to-get-the-maximum-id-value-in-elasticsearch 的原因. 因为 --sync 功能需要排序, 所以默认采用了 _id(我只通过 docker 尝试并验证了 6.x 及以后的版本, 确实没有测试 5.x 版本) , 你可以尝试加入 --sort= ( 表示不指定排序字段 ), 应该可以规避这个问题.

如果想使用 --sync 功能的话, 必须指定排序字段. 如果你的 src/dst 数据中有唯一可以排序的字段(比如你们自己的业务 id), 可以尝试以下命令(最好先在一些不重要的 index 上测试):

/usr/local/esm/bin/esm --sync --sort="你的业务ID" -s http://10.10.8.50:9201 -x umedia_correction_sd_www_202212 
  -d http://10.10.7.51:8201 -y umedia_correction_sd_www_202212 -u "_doc"

你好!本次运行中却又出现其它问题
image
它并没有明显的错误信息就直接退出运行程序,我甚至都无从下手去找出问题所在

@fishjam
Copy link

fishjam commented Mar 20, 2024

你这很奇怪. 按我执行 --sync 的效果,应该有类似如下的日志, 但你的完全看不到.

[03-20 00:02:13] [INF] [ migrator.go:115 ,ParseEsApi] source es version: 7.17.9
[03-20 00:02:13] [INF] [ migrator.go:115 ,ParseEsApi] dest es version: 6.2.2
[03-20 00:02:14] [INF] [ migrator.go:424 ,SyncBetweenIndex] src total count=34023
[03-20 00:02:22] [INF] [ migrator.go:575 ,SyncBetweenIndex] src-index-202402(34023) to dest-index-202402(33963), add=60, update=0, delete=0
  1. 你执行命令的方式? 应该是没有使用 --sync 方式 ?
  2. esm 的版本( 可以执行 esm -h 并贴上结果),
  3. 确认并确保 core dump 能生成( 但从日志来看, 你的执行应该没有core)
  4. 增加 --log=info 参数, 并且通过重定向(或 tee)的方式, 将完整日志保存下来. 比如 /usr/local/esm/bin/esm 各种参数 >> sync_es.log 2>&1 , 并提交.

@lianmeng0
Copy link
Author

你这很奇怪. 按我执行 --sync 的效果,应该有类似如下的日志, 但你的完全看不到.

[03-20 00:02:13] [INF] [ migrator.go:115 ,ParseEsApi] source es version: 7.17.9
[03-20 00:02:13] [INF] [ migrator.go:115 ,ParseEsApi] dest es version: 6.2.2
[03-20 00:02:14] [INF] [ migrator.go:424 ,SyncBetweenIndex] src total count=34023
[03-20 00:02:22] [INF] [ migrator.go:575 ,SyncBetweenIndex] src-index-202402(34023) to dest-index-202402(33963), add=60, update=0, delete=0
  1. 你执行命令的方式? 应该是没有使用 --sync 方式 ?
  2. esm 的版本( 可以执行 esm -h 并贴上结果),
  3. 确认并确保 core dump 能生成( 但从日志来看, 你的执行应该没有core)
  4. 增加 --log=info 参数, 并且通过重定向(或 tee)的方式, 将完整日志保存下来. 比如 /usr/local/esm/bin/esm 各种参数 >> sync_es.log 2>&1 , 并提交.

你好!非常抱歉,又来打搅您了。本次按你的要求添加各种参数去执行迁移命令。
这是ESM截图
企业微信截图_20240325103045
使用的命令:
/usr/local/esm/bin/esm7 --sync --sort="id" -s http://10.10.8.50:9201 -x umedia_net_manage_content_check_www_201801 -d http://10.10.7.51:8201 -y umedia_net_manage_content_check_www_201801 -w 10 -b 20 -u "_doc" -c 5000 --sliced_scroll_size=5 --buffer_count=300000 -t 180m --log=info --refresh >> sync_es.log 2>&1
但是运行后却是报错:
{"index":{"_index":"umedia_net_manage_content_check_www_201801","_type":"doc","_id":"0445309d381d38fa858bd8de299f2528","status":400,"error":{"type":"illegal_argument_exception","reason":"Invalid type: expecting [_doc] but got [doc]"}}}
然后就是程序停止,日志输出也停止:
企业微信截图_20240325113340
企业微信截图_20240325113633

@fishjam
Copy link

fishjam commented Mar 28, 2024

经过确认, 是在增加 --sync 功能时, 没有支持 -u 参数, 且没有在 es 5.x 的版本上测试.
可以下载以下编译好的 esm 进行测试(注意: 不要使用 -w/-b/-c 等参数, 在 sync 功能中没有使用, 且会造成数据错误), 如果确认 OK 的话, 我会提交 PR.

esm-linux-amd64.zip
esm-windows-amd64.zip

自测方式( docker )

    1. 创建 es 5.6.4 的 docker 作为 src , 并引入数据(官方的 accounts )
docker run -ti --rm -p 9200:9200 -e cluster.name=es_src --name es_src elasticsearch:5.6.4
curl -H "Content-Type: application/json" -X POST "localhost:9200/bank/account/_bulk?pretty" --data-binary  @accounts.json
    1. 创建 es 7.17.0 的 docker 作为 dst ( 没有找到 7.15.1 的镜像)
docker run -ti --rm --privileged --name es_dst
  -e discovery.type=single-node -e discovery.seed_hosts=127.0.0.1 -e cluster.name=es_dst -p 9201:9200
  elasticsearch:7.17.0 bash -c "ulimit -l unlimited && sysctl -w vm.max_map_count=262144 && /usr/local/bin/docker-entrypoint.sh"
    1. 同步数据
esm --sync --sort="account_number" -s http://127.0.0.1:9200 -x bank -d http://127.0.0.1:9201 -y bank -u "_doc"
    1. 导出数据并比较( 排除不同的 _type 字段, 如果完全相同, 则 diff 没有任何输出 )
esm --sort=account_number -s http://localhost:9200 -x bank --truncate_output --skip=_type -o=src.json
esm --sort=account_number -s http://localhost:9201 -x bank --truncate_output --skip=_type -o=dst.json
diff -W 200 -ry --suppress-common-lines src.json dst.json

@lianmeng0
Copy link
Author

经过确认, 是在增加 --sync 功能时, 没有支持 -u 参数, 且没有在 es 5.x 的版本上测试. 可以下载以下编译好的 esm 进行测试(注意: 不要使用 -w/-b/-c 等参数, 在 sync 功能中没有使用, 且会造成数据错误), 如果确认 OK 的话, 我会提交 PR.

esm-linux-amd64.zip esm-windows-amd64.zip

自测方式( docker )

    1. 创建 es 5.6.4 的 docker 作为 src , 并引入数据(官方的 accounts )
docker run -ti --rm -p 9200:9200 -e cluster.name=es_src --name es_src elasticsearch:5.6.4
curl -H "Content-Type: application/json" -X POST "localhost:9200/bank/account/_bulk?pretty" --data-binary  @accounts.json
    1. 创建 es 7.17.0 的 docker 作为 dst ( 没有找到 7.15.1 的镜像)
docker run -ti --rm --privileged --name es_dst
  -e discovery.type=single-node -e discovery.seed_hosts=127.0.0.1 -e cluster.name=es_dst -p 9201:9200
  elasticsearch:7.17.0 bash -c "ulimit -l unlimited && sysctl -w vm.max_map_count=262144 && /usr/local/bin/docker-entrypoint.sh"
    1. 同步数据
esm --sync --sort="account_number" -s http://127.0.0.1:9200 -x bank -d http://127.0.0.1:9201 -y bank -u "_doc"
    1. 导出数据并比较( 排除不同的 _type 字段, 如果完全相同, 则 diff 没有任何输出 )
esm --sort=account_number -s http://localhost:9200 -x bank --truncate_output --skip=_type -o=src.json
esm --sort=account_number -s http://localhost:9201 -x bank --truncate_output --skip=_type -o=dst.json
diff -W 200 -ry --suppress-common-lines src.json dst.json

你好!使用该方法依然报错,这是报错截图:
image
这是使用的命令:
/root/esm-linux-amd64 --sync --sort="id" -s http://10.10.8.51:9201 -x umedia_net_manage_content_check_www_202205 -d http://10.10.7.52:8201 -y umedia_net_manage_content_check_www_202205 -u "_doc"

我确定我这边的服务链接正常,集群稳定

@fishjam
Copy link

fishjam commented Mar 29, 2024

@lianmeng0 从出错状态和代码来看, 是向服务器发送 更新请求以后, 返回状态不对( 非 200), 而且没有从服务器读到响应信息( server error 后为 空).
看是否可以提供 tcpdump 对 dest es 发送请求的抓包情况.
根据你的执行情况, 在执行 esm 前,另开一个终端, 执行以下命令(以下是 centos 的抓包命令, 如果提示错误, 可先自行度娘解决):

  sudo /sbin/tcpdump -nn -vvv -i any "host 10.10.7.52 and port 8201" -w dst_es.pcap 

然后执行 esm 后, 将 dst_es.pcap 提供( 注意: 其大小应该大于 24 字节, 表示抓到了包 ).
如果觉得数据不能通过 github 这种公开的渠道提供, 可以给我发邮件: [email protected]

@fishjam
Copy link

fishjam commented Mar 30, 2024

可以使用这个新的包测试一下.
使用方式:

  1. 推荐: 将之前已经同步过的目标 index 删除, 因为采用 --sync 时使用了完全不同的方式, 有可能以前同步过的数据会冲突.
  2. 使用命令( 更改了 --sort 参数, 拆分成了 --ssort 和 --dsort 从而支持两者 es5/es7 不一样的排序字段 )
  3. 如果失败,可能会生成一个名为 esm.log 的文件,记录了 error 日志, 可以提供其最后的内容.
./esm-linux-amd64 --sync 
  --ssort="id" -s http://10.10.8.51:9201/ -x umedia_net_manage_content_check_www_202205 
  --dsort="id" -d http://10.10.7.52:8201/ -y umedia_net_manage_content_check_www_202205 -u "_doc"

esm-linux-amd64.zip

@lianmeng0
Copy link
Author

可以使用这个新的包测试一下. 使用方式:

  1. 推荐: 将之前已经同步过的目标 index 删除, 因为采用 --sync 时使用了完全不同的方式, 有可能以前同步过的数据会冲突.
  2. 使用命令( 更改了 --sort 参数, 拆分成了 --ssort 和 --dsort 从而支持两者 es5/es7 不一样的排序字段 )
  3. 如果失败,可能会生成一个名为 esm.log 的文件,记录了 error 日志, 可以提供其最后的内容.
./esm-linux-amd64 --sync 
  --ssort="id" -s http://10.10.8.51:9201/ -x umedia_net_manage_content_check_www_202205 
  --dsort="id" -d http://10.10.7.52:8201/ -y umedia_net_manage_content_check_www_202205 -u "_doc"

esm-linux-amd64.zip

你好!这是测试产生的error日志最后的内容:
net/http: HTTP/1.x transport connection broken: write tcp 10.10.7.55:36710->10.10.8.51:9201: write: connection reset by peer
[04-01 17:50:08] [ERR] [ v0.go:414 ,DeleteScroll] server error: code=400, length=-1, info={"error":{"root_cause":[{"type":"illegal_argument_exception","reason":"request [//_search/scroll] contains unrecognized parameter: [scroll_id]"}],"type":"illegal_argument_exception","reason":"request [//_search/scroll] contains unrecognized parameter: [scroll_id]"},"status":400}
[04-01 17:50:08] [WRN] [ verify.go:54 ,checkAndHandleError] E:/CodeGo/fishjam-esm/migrator.go:594: (SyncBetweenIndex) FAIL(*errors.errorString), msg=server error: code=400, length=-1, info={"error":{"root_cause":[{"type":"illegal_argument_exception","reason":"request [//_search/scroll] contains unrecognized parameter: [scroll_id]"}],"type":"illegal_argument_exception","reason":"request [//_search/scroll] contains unrecognized parameter: [scroll_id]"},"status":400}
Progress 0 / ? [---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------=] 0s
Source End
[04-01 17:50:08] [INF] [ migrator.go:605 ,SyncBetweenIndex] sync umedia_net_manage_content_check_www_202205(0/0) to umedia_net_manage_content_check_www_202205(0), add=0, update=0, delete=0

全部内容已发送到邮件:[email protected] 还请查收

@fishjam
Copy link

fishjam commented Apr 2, 2024

看来是我给的示例命令有点问题, 改成如下试试 ( 删除了 -s 和 -d 参数后面的最后一个 "/" ),

./esm-linux-amd64 --sync 
  --ssort="id" -s http://10.10.8.51:9201 -x umedia_net_manage_content_check_www_202205 
  --dsort="id" -d http://10.10.7.52:8201 -y umedia_net_manage_content_check_www_202205 -u "_doc"

@fishjam
Copy link

fishjam commented Apr 9, 2024

@lianmeng0 你好,现在怎么样?

@lianmeng0
Copy link
Author

lianmeng0 commented Apr 15, 2024

@lianmeng0 你好,现在怎么样?

很抱歉,这么久才回复。目前你提供的示例命令运行有误,不知是否是参数问题还是其它,错误如下:
./esm-linux-amd64 --sync
--ssort="id" -s http://10.10.8.51:9201 -x umedia_net_manage_content_check_www_202205
--dsort="id" -d http://10.10.7.52:8201 -y umedia_net_manage_content_check_www_202205 -u "_doc"
当执行命令时,会有如下日志输出:
[04-15 14:37:49] [ERR] [ v0.go:83 ,Bulk] server error: code=413, length=0, info=
[04-15 14:37:49] [WRN] [ verify.go:54 ,checkAndHandleError] E:/CodeGo/fishjam-esm/migrator.go:383: (bulkRecords) FAIL(*errors.errorString), msg=server error: code=413, length=0, info=

添加参数限制 -c 5000 也还是有相同的错误告警
然后还有其它的告警,我是在10.10.9.55主机上运行的命令:
Progress 150000 / 6609750 [===>-----------------------------------------------------------------------------------------------------------------------------------------------------------] 2.27% 2h40m54s[04-15 10:26:41] [ERR] [ http.go:227 ,Request] Post "http://10.10.4.19:8201/_bulk": readfrom tcp 10.10.9.55:57662->10.10.4.19:8201: write tcp 10.10.9.55:57662->10.10.4.19:8201: write: broken pipe
[04-15 10:26:41] [ERR] [ v0.go:83 ,Bulk] Post "http://10.10.4.19:8201/_bulk": readfrom tcp 10.10.9.55:57662->10.10.4.19:8201: write tcp 10.10.9.55:57662->10.10.4.19:8201: write: broken pipe
[04-15 10:26:41] [WRN] [ verify.go:54 ,checkAndHandleError] E:/CodeGo/fishjam-esm/migrator.go:383: (bulkRecords) FAIL(*url.Error), msg=Post "http://10.10.4.19:8201/_bulk": readfrom tcp 10.10.9.55:57662->10.10.4.19:8201: write tcp 10.10.9.55:57662->10.10.4.19:8201: write: broken pipe
当然,命令程序并没有中止,还在正常运行。

这是命令执行后的开始日志:
企业微信截图_20240415102624
这是命令执行后的结束日志:
image
但是在目的集群中并没有索引的文档
image

这是日志中关键的地方:
[04-01 17:50:08] [ERR] [ v0.go:414 ,DeleteScroll] server error: code=400, length=-1, info={"error":{"root_cause":[{"type":"illegal_argument_exception","reason":"request [//_search/scroll] contains unrecognized parameter: [scroll_id]"}],"type":"illegal_argument_exception","reason":"request [//_search/scroll] contains unrecognized parameter: [scroll_id]"},"status":400}

说请求参数不正确,整个日志已发送到你的邮箱,还请注意查收

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants