当前位置:首页 > 文章列表 > 数据库 > Redis > Redis ZRANGE 怎样实现带游标的有序集合分页

Redis ZRANGE 怎样实现带游标的有序集合分页

来源:17golang原创 2026-10-26 01:37:26 0浏览 收藏

Redis Sorted Set 如果用固定的 LIMIT offset count 做深分页,页码越靠后,服务端越需要跳过前面的成员;而且新增或删除成员后,后续页可能发生漂移。更稳妥的做法是把上一页最后一条记录的 score 当成游标,下一页用 ZRANGE ... BYSCORE 从这个分值之后继续取。

首屏从 -inf 开始,后续请求保存上一页最后一条数据的 score,并把它写成 (last_score 作为排他起点。若业务允许相同 score,必须让分页排序键唯一,或额外设计同分值的 tie-breaker,否则可能跳过同分值成员。

官方资料:https://redis.io/docs/latest/commands/zrange/

要点速览
  • ZRANGE 从 Redis 6.2 起可以用 BYSCORE 按分值查询,并配合 LIMIT 返回一页。
  • 下一页使用排他的 (last_score,避免把上一页最后一条再次返回。
  • 游标分页解决的是“从哪里继续”,不是自动解决重复 score;生产数据要保证排序键可稳定推进。

先把首屏查询改成分值游标

假设有一个按发布时间排序的文章集合,成员是文章 ID,score 是已经构造好的递增排序值。首屏不需要知道页码,直接把分值范围写成 -inf 到 +inf,再用 LIMIT 0 3 取三条。

Redis ZRANGE 以 Sorted Set、score 游标、BYSCORE 范围和 LIMIT 分页组成的静态关系说明图
图1:结构说明图,展示 Sorted Set、分值范围、游标和一页结果之间的关系,不是 Redis 控制台或运行截图。
# 先写入一组按 score 排序的文章成员,score 在这个示例中是唯一递增值
redis-cli ZADD article:publish 1001 article-a 1002 article-b 1003 article-c 1004 article-d 1005 article-e

# 首屏从负无穷开始,最多返回 3 个成员,并带回 score 供下一页使用
redis-cli ZRANGE article:publish -inf +inf BYSCORE LIMIT 0 3 WITHSCORES

首屏返回的最后一组值是 article-c 和 1003。真正需要交给客户端的不是“第 2 页”,而是这个边界值 1003。客户端可以把它放进下一次请求的 cursor 字段。

用排他边界推进下一页

下一页的关键是给起始 score 加一对圆括号:(1003 表示严格大于 1003。它与普通的 1003 不同,后者会把 score 等于 1003 的成员重新纳入范围。

Redis ZRANGE 下一页使用排他游标并输出下一条成员的静态边界说明图
图2:边界说明图,展示上一页末尾、排他起点和下一页成员的静态关系,不是命令执行结果截图。
# 1003 已经属于上一页,所以用 (1003 排除它,继续取后面的 3 条
# LIMIT 的 offset 从 0 开始,count 是本页最多返回的成员数
redis-cli ZRANGE article:publish (1003 +inf BYSCORE LIMIT 0 3 WITHSCORES

这样得到的是 article-d、article-e 等分值更大的成员。接口通常返回两部分:数据数组和下一次 cursor。下一次 cursor 应取当前页最后一条的 score;如果本页为空,则直接认为已经到达当前集合末尾。

重复 score 时,游标必须还能稳定推进

很多业务会把秒级时间戳直接当 score,这会让同一秒写入的多个成员共享分值。只保存 score 时,使用 (last_score 会一次性排除所有同分值成员,可能造成漏读;改成包含边界又会重复上一页数据。

一种简单做法是写入时构造唯一递增的排序值,例如用毫秒时间配合受控序号生成单调整数,并确保不会超过 Redis double 能精确表示的整数范围。另一种做法是把“score + member”都放进游标,在客户端或 Lua 逻辑中先处理同分值成员,再跳到更大的 score;这时要明确 member 的字典序规则,不能只凭字符串长度猜顺序。

数据条件推荐游标主要风险
score 唯一递增只保存最后一条 score写入端必须维持单调性
大量成员共享 scorescore + member需要实现同分值的字典序推进
数据会频繁插入旧分值固定排序规则与快照语义新数据可能出现在已读区间,需明确是否接受

判断末页并控制查询成本

如果本页返回数量小于请求的 pageSize,通常可以把它作为“当前集合已读完”的信号;如果恰好等于 pageSize,则继续使用最后一条的 score 请求下一页。不要把返回空数组当成永久没有数据,因为集合可能在下一次请求前发生新增。

Redis 官方文档给出的 ZRANGE 复杂度是 O(log(N)+M),其中 M 是返回数量。游标分页把每次查询的结果量固定在 pageSize 附近,通常比不断增大的 offset 更适合长列表;但它仍然不等于数据库快照,跨请求的数据变化需要由业务决定是否允许重复、漏读或使用版本标记。

  • 不要保存页码代替游标:页码无法表达数据在请求之间插入或删除后的真实位置。
  • 不要忘记排他符号:没有 ( 时,边界成员会在下一页重复出现。
  • 不要忽略 score 精度与同分值:排序值必须可稳定比较,必要时把唯一序号纳入排序模型。

总结这条链路:首屏用 -inf,后续页使用上一页末尾的排他 score,结果数量负责判断是否继续,写入模型负责保证游标不会跳过同分值成员。这样做,ZRANGE 才真正具备可交付的游标分页语义。

常见问题

为什么下一页要写成 (1003?

圆括号表示排他起点,下一页只取 score 严格大于 1003 的成员,可以避免上一页最后一条被重复返回。

score 相同能不能只保存最后一个 score?

不建议。排他 score 会跳过剩余同分值成员,包含 score 又会产生重复;应让排序值唯一,或把 member 的稳定顺序纳入游标。

ZRANGE 的 LIMIT 还能写 offset 吗?

可以,但在游标分页中通常固定为 0,把“从哪里开始”交给分值游标表达;较大的 offset 更像深分页,不能获得同样稳定的推进语义。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Redis HSCAN 怎样分批导出大型哈希中的字段Redis HSCAN 怎样分批导出大型哈希中的字段
上一篇
Redis HSCAN 怎样分批导出大型哈希中的字段
Redis Lua 脚本怎样返回多个状态值
下一篇
Redis Lua 脚本怎样返回多个状态值
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    693次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    706次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    774次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    734次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    567次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码