1. 课程导入与业务场景拆解

在开始写第一行 Redis 命令之前,我们需要先弄清楚一件事:这门课要解决的到底是什么问题。很多同学一听到"排行榜"就想到 ZSET,一听到"计数器"就想到 INCR,但真正落到业务里,往往会在"用哪个结构""数据怎么存""什么时候更新""榜单怎么分页""计数会不会丢"这些细节上卡住。本章的目标不是给出答案,而是把问题拆清楚——先看清业务长什么样,再决定 Redis 在其中扮演什么角色。

一、实时排行榜与计数业务到底"实时"在哪里

传统做法是把积分、销量、点赞数写进关系型数据库,需要榜单时用 ORDER BY score DESC LIMIT 100 查一次。这套方案在数据量小、更新频率低时完全够用,但一旦进入"实时"场景就会暴露三个硬伤:

  • 写入压力:一次点赞就是一次 UPDATE,热门内容每秒可能被更新上千次,行锁和写放大让数据库很快成为瓶颈。
  • 查询延迟:每次刷新榜单都要对全表或大范围数据排序,数据量到百万级后,即使有索引,深分页和排序开销也不可接受。
  • 时效性:用户刚投完票,榜单要"立刻"变化。数据库主从复制、缓存过期策略都会引入秒级甚至更长的延迟。

所谓"实时",在工程上通常指写入后百毫秒级内可被榜单查询感知。Redis 把数据放在内存中,单机读写可达十万级 QPS,天然适合承担"高频写入 + 低延迟读取"的中间层角色。它不是要取代数据库,而是把"热数据"和"高频操作"从数据库里剥离出来。

二、四类典型场景与它们的差异

同样是排行榜,不同业务的约束差别很大,直接决定了数据结构选型和更新策略。下面这张图把四类典型场景的核心特征、数据形态和 Redis 角色放在一起对照,便于建立整体认知。

四类实时排行榜 / 计数场景对照 核心差异:更新频率 · 排序维度 · 数据规模 · 一致性要求 场景 典型数据形态 更新特征 排序维度 Redis 角色 游戏积分榜 玩家ID → 分数 全服 / 分区 member=玩家ID score=累计积分 分数单调递增 对局结束批量写入 峰值集中、可容忍 秒级延迟 分数降序 同分按时间 Top N + 个人排名 ZSET 主存储 ZINCRBY / ZREVRANGE ZREVRANK 查排名 电商销量榜 商品ID → 销量 日榜 / 周榜 member=商品ID score=销量 按周期重置 下单即 +1 持续高频写入 需防刷单 销量降序 分页展示 Top 100 ZSET + 过期键 按天建 key 定时合并 社交热度榜 话题ID → 热度 点赞/评论/转发 member=话题ID score=加权热度 多行为加权 点赞+1 评论+3 转发+5 热度随时间衰减 热度降序 滑动窗口 Top 50 ZSET + 定时衰减 ZINCRBY 加权 后台任务重算 实时计数器 资源ID → 计数值 PV/UV/点赞数 key=资源ID value=整数 无需排序 每次访问 +1 极高并发 要求原子性 无排序 只读单值 可批量读取 String INCR INCR / INCRBY MGET 批量读

从图中可以读出几个关键判断:游戏积分榜的分数是单调递增的,写入集中在对局结束,对延迟容忍度相对高;电商销量榜需要按天/周重置,key 的命名和过期策略比数据结构本身更重要;社交热度榜的分数不是简单累加,而是多行为加权并随时间衰减,需要额外的重算逻辑;实时计数器则完全不需要排序,用最简单的 String 就能解决。把场景特征先对齐,后面的选型才不会走偏。

三、Redis 在架构中的角色定位

需要特别强调的是:Redis 在这类业务中通常不是唯一数据源。以电商销量榜为例,订单数据必须落库保证不丢,Redis 里的销量榜是"派生数据"——它可以从数据库重算出来。这种定位带来两个重要推论:

  1. 允许最终一致:Redis 写入失败或实例重启导致榜单短暂不准,可以通过重算修复,不必像订单表那样要求强一致。
  2. 需要设计回源与重建路径:当缓存丢失或数据异常时,要能从数据库重新灌入榜单。这条路径必须在设计阶段就想清楚,而不是等线上出问题再补。

反过来,如果是"点赞数"这种允许少量误差、但要求极高并发的计数,Redis 可以直接作为权威计数源,再异步落库。所以"Redis 是缓存还是主存储"没有统一答案,取决于业务对一致性和持久性的要求。

四、动手前先明确四个问题

在进入具体命令和代码之前,建议对每个排行榜/计数需求先回答下面四个问题。它们会直接决定后续的 key 设计、结构选型和更新策略:

问题为什么重要示例回答
排序维度是什么? 决定用 ZSET 还是 String 按积分排序 → ZSET;只统计总数 → String
更新频率与峰值? 决定是否需要批量/异步写入 每秒 5000 次点赞 → 考虑合并写入
榜单周期? 决定 key 命名与过期策略 日榜 → rank:sales:20240601,TTL 7 天
数据能否重算? 决定一致性要求与容错方案 能从订单表重算 → 允许最终一致
这四个问题不需要一次答得完美,但必须在写代码前有明确倾向。很多线上事故的根源不是 Redis 用错了命令,而是"榜单周期没定义清楚"或"没想好数据丢了怎么办"。

五、本课程将覆盖的能力地图

接下来的章节会沿着"场景 → 结构 → 命令 → 工程化"这条线展开。你会学到如何用 ZADD、ZINCRBY、ZREVRANGE、ZREVRANK 构建排行榜,如何处理同分排序和分页,如何用 INCR 系列命令做高并发计数,如何设计 key 的命名与过期,以及如何应对缓存穿透、热点 key、数据重建等工程问题。本章建立的场景认知,是后面所有技术决策的判断依据。