Redis 入门 06:排行榜与计数器综合练习
实验基线:Redis 7.4.11,先完成环境准备。除标注为宿主机终端的代码外,Redis 命令在该课指定的 redis-cli 中执行;不复制输出结果作为命令。
学习目标#
把键、Hash、计数器和 Sorted Set 组合成一个“每日答题活动”,能独立设计命令并解释重复提交的风险。
需求与建模#
活动日采用固定示例 2026-10-12,业务使用哪个时区必须事先定义。排行榜键为 learn:project:2026-10-12
榜单记录每人总得分,访问计数记录次数,Hash 保存展示姓名。实验只保留 24 小时;这表示写入后 86400 秒,不是当地午夜到期。需要午夜到期时,应计算时间戳并使用 EXPIREAT。
实验:初始化与提交#
先清理本课键,再执行,保证参考输出可复现:
UNLINK learn:project:2026-10-12:rank learn:project:2026-10-12:views learn:project:user:alice
HSET learn:project:user:alice name Alice city Shanghai
ZADD learn:project:2026-10-12:rank 0 alice 0 bob
ZINCRBY learn:project:2026-10-12:rank 20 alice
ZINCRBY learn:project:2026-10-12:rank 30 bob
ZINCRBY learn:project:2026-10-12:rank 15 alice
INCR learn:project:2026-10-12:views
INCR learn:project:2026-10-12:views
EXPIRE learn:project:2026-10-12:rank 86400
EXPIRE learn:project:2026-10-12:views 86400
EXPIRE learn:project:user:alice 86400
alice 依次得到 20 和 35,bob 得到 30,访问计数最终为 2。EXPIRE 返回 1。此处每条命令是原子的,但整组操作没有原子性保证;真实业务不能保证排行榜和访问计数同时更新。
验收:自己先预测结果#
ZREVRANGE learn:project:2026-10-12:rank 0 9 WITHSCORES
ZREVRANK learn:project:2026-10-12:rank alice
HGET learn:project:user:alice name
GET learn:project:2026-10-12:views
TTL learn:project:2026-10-12:rank
预期:alice 35、bob 30;alice 排名为 0;姓名 Alice;访问次数 2;TTL 在 0 到 86400 内。如果结果不一致,先检查是否重复运行命令以及 TTL 是否已经过去。
常见错误与设计边界#
同一答题请求重试两次,ZINCRBY 会执行两次。不能仅靠最终总分判断有没有重复提交;需要请求 ID、幂等记录,以及提交业务与计分之间的协调。
榜单不是按姓名存成员。姓名可能修改或重复,应使用稳定用户 ID,展示时再读取档案。不要为所有榜单成员逐个串行读取档案,大规模读取应使用批量或 Pipeline,但它不会自动提供原子性。
练习与参考答案#
让 bob 再得 10 分,读取新的前两名;记录一次访问,查 alice 展示排名:
ZINCRBY learn:project:2026-10-12:rank 10 bob
INCR learn:project:2026-10-12:views
ZREVRANGE learn:project:2026-10-12:rank 0 1 WITHSCORES
ZREVRANK learn:project:2026-10-12:rank alice
答案:bob 40 第一,alice 35 第二;访问次数 3;alice 返回排名 1,页面展示第 2。思考:INCR 后程序崩溃导致 EXPIRE 未执行,怎样保证两者一起完成?下一阶段用 Lua 解决。
清理#
UNLINK learn:project:2026-10-12:rank learn:project:2026-10-12:views learn:project:user:alice
完成入门阶段的标准:可以不看答案选择结构、预测输出,并说明 TTL、原子命令与业务事务之间的区别。







