Redis 搜索应用 · 交互实验

评分与翻页实验室

同一批候选结果,权重稍微一动,名次就会重排;翻页中途再来一条新数据,OFFSET 与游标也会走向不同的结果。先动手,再讨论边界。

ZSET 实时排名

总分降序;显示分数相同时,以唯一 ID 降序固定位置,与 ZREVRANGE 的方向一致。

10 个成员

当前没有显示分数并列。拖动滑块可能制造并列;无论如何,唯一 ID 都会给排序一个确定结局。

两条翻页轨道,同一次数据变动

每页 3 条。请先让两边各读一页,再插入“Redis 搜索排障清单”;它会落在已经读过的边界之前。接着翻页,就能看到两种续读条件如何应对排名位移。

实验页大小:3

尚未插入。先让两条轨道各读取第一页,现象最清楚。

OFFSET 深翻页

下一页依赖“跳过多少条”,却不记得上一页最后是谁。

OFFSET 0
ZREVRANGE search:rank 0 2 WITHSCORES

基于(分数,ID)的游标续读

下一页严格从上一页最后一个二元组之后继续。

游标:起点
按 score DESC, id DESC 读取前 3 条

OFFSET 的风险来自位置会移动

插入、删除或改分都可能让旧成员换到新下标。客户端仍然机械地跳过 3、6、9 条,于是同一成员可能再出现,也可能有成员永远没被读到。页数越深,需要跳过的范围也越大,但本页不对耗时作虚构测量。

游标给的是边界,不是快照

“分数 + 唯一 ID”能在并列分数时建立完整顺序,并让续读条件保持严格。它可以避免边界之前的新记录把已读成员推回来;但边界之前后来插入的数据不会自动补发,若业务要求绝对一致,仍需版本号、快照或固定查询时刻。

为什么先归一化

三个指标即使都写成数字,量纲和分布也可能不同。实验按评分协议预先约定的 0~100 标尺逐项做 min-max 归一化,再归一化权重,避免某个指标只因数值范围更大就垄断总分。

并列时为何还要 ID

只比较分数不是完整排序。两个成员同分时若没有第二关键字,翻页边界会含糊。把唯一 ID 加进比较规则,得到可复现的全序:分数降序,ID 降序;这也与 ZREVRANGE 的同分成员方向一致。

落到 Redis 怎么想

  1. 用 ZSET 保存可排序分数与成员 ID。
  2. 把筛选条件、评分版本绑定到游标上下文。
  3. 游标保存最后一条的 score 与 ID,并做严格续读。