DEBUG.WIKI
OnlineSIM:在线接收短信,虚拟号码租用
IPPeak:从目标地区访问网页,住宅代理、SEO 监测、广告验证
腾讯云;让你的想法跑起来;轻量服务器 · 建站 / Docker / API;查看产品 →

go-redis 搜索游标读不到下一页,检查 32 位 int 截断

FTAggregate返回int64游标,FTCursorRead却接收int。32位目标上的大游标可能发送前已截断,需保留完整ID并检查显式命令与结果解析。

搜索聚合第一页正常,继续读取却找不到游标,服务器收到的ID还和第一页返回的不同。若程序运行在 GOARCH=386 或采用32位 int 的目标上,应检查游标有没有在调用前被截断。

go-redis v9.23.0 的聚合结果游标使用 int64,但 FTCursorRead、FTCursorDel 的游标参数仍是 int;游标构建器也有将ID转成 int 的路径。64位开发机正常,不代表32位构建同样能保留这个值。

在类型转换前后比较同一个ID

先记录实际构建目标、游标原始类型,以及调用前后的十进制ID。不要用浮点数保存游标,也不要先转成 int 再转回 int64:第一次窄化丢掉的高位不会恢复。

该条件针对超过32位有符号整数范围的游标。小ID偶尔正常,只能说明当时未超过范围,不能证明整条类型链是安全的。

也要排除索引名不一致、游标已过期或已读完。这些情况同样可能无法继续读取,但不要求ID在发送前发生变化。

绕开窄化参数时,保留完整值

在已确认的32位兼容需求中,可沿项目原有客户端发送显式命令,使ID保持 int64,不经过那个 int 参数。例如:

reply, err := rdb.Do(ctx,
    "FT.CURSOR", "READ", indexName, cursorID, "COUNT", 100,
).Result()

cursorID 必须仍是从聚合响应保存下来的完整 int64,indexName 是原索引,rdb 与 ctx 沿用项目现有对象。100是示例批量大小。

Do().Result() 返回的是通用结果,不会自动变成 FTAggregateResult。应用需按实际RESP协议与搜索响应结构解析行、错误和下一游标;不能只改调用这一行,然后沿用不匹配的强制类型断言。

显式删除游标同样需要保留完整ID,但删除应只针对这次操作实际拥有且不再需要的游标。不要截断后尝试删除,也不要在读取失败时遍历删除其他业务游标。

如果可以改用受支持的64位构建,应同时验证部署架构与依赖,不只修改开发机环境变量。改了目标架构也不等于客户端API已经统一支持所有无符号64位值;后续接口变更还可能影响mock与调用方签名。

验证完整分页与释放

在测试索引上核对完整ID从返回、存储到下一次发送都未变化,再比较多页结果与预期总量。分别检查游标归零、过期、主动结束和错误路径,确认没有漏页、重复处理或遗留本次游标。

这是 FT.CURSOR 搜索游标,不应套用普通 SCAN 的返回结构或结束约定。对超出当前客户端可表示范围的值,应明确失败并保留证据,不能用截断后的数字继续操作。