学完这篇,你能对号入座地为每个业务场景选对 Redis 数据类型,并知道对应的核心命令和最容易踩的坑。
第一步:先连上 redis-cli,边看边敲
别只看文档,动手敲一遍记得最牢:
redis-cli -h 127.0.0.1 -p 6379 -a 你的密码
127.0.0.1:6379> PING
PONG
登录后先 SELECT 0 确认库号,DBSIZE 看当前有多少 key,TYPE 你的key 查某个 key 到底是什么类型——排查线上问题时,这条命令用得最多。
注意:KEYS * 在数据量大时会阻塞整个实例,线上改用 SCAN 0 MATCH user:* COUNT 100 游标遍历。
第二步:String——最简单的万能口袋
最基础的类型,能存字符串、数字、序列化后的 JSON,单值最大 512MB。
SET user:1:name "阿乐" EX 3600 # 带过期时间
SET lock:order:1001 "1" NX EX 10 # 不存在才设置,10 秒过期
INCR article:1:views # 原子自增
GET article:1:views
典型场景:
- 缓存对象:
SET user:1 '{...json...}' EX 300
- 计数器:阅读数、点赞数用
INCR,天然原子,不会并发写丢
- 分布式锁:必须是
SET key val NX EX 秒数 一条命令搞定
注意:老教程爱写 SETNX 再单独 EXPIRE,这两条不是原子的,中间进程挂掉就变成永不过期的死锁。用 SET ... NX EX 一条命令替代。
第三步:Hash——存对象,别再整条 JSON 覆盖
Hash 是「字段 → 值」的映射,适合存结构化的对象,改一个字段不用把整个对象读出来再写回去。
HSET user:1 name "阿乐" age 30 city "杭州"
HGET user:1 name
HINCRBY user:1 age 1
HGETALL user:1
HDEL user:1 city
典型场景:用户资料、商品属性、购物车(HSET cart:1001 sku:88 2)。
注意:HGETALL 会把所有字段一次性拉回客户端,字段上千个时会明显卡顿。字段多的 Hash 用 HSCAN user:1 0 COUNT 50 分批读。另外 Hash 没有单字段过期(Redis 7.4 起才有 HEXPIRE),老版本要自己在值里存时间戳。
第四步:List——队列和最新列表
底层是双向链表,两头进出都快,按索引随机访问慢。
LPUSH news:latest "文章A" # 左侧插入
RPUSH queue:mail "任务1" # 右侧入队
LPOP queue:mail # 左侧出队,先进先出
BLPOP queue:mail 5 # 阻塞版,最多等 5 秒
LRANGE news:latest 0 9 # 取最新 10 条
LTRIM news:latest 0 99 # 只保留前 100 条
典型场景:最新动态列表(LPUSH + LTRIM 保持定长)、简单任务队列(RPUSH + BLPOP)。
注意:List 当队列用是「尽力而为」,消费者取走数据后崩溃就丢了,没有 ACK 机制。要可靠队列用 Stream(XADD / XREADGROUP),或者直接上专业 MQ。另外 LRANGE key 0 -1 取全量列表在大 List 上很危险。
第五步:Set——去重和集合运算
无序、自动去重,支持交集并集差集。
SADD article:1:likes 1001 1002 1003
SISMEMBER article:1:likes 1001 # 判断是否点过赞,O(1)
SCARD article:1:likes # 点赞总数
SINTER user:1:follow user:2:follow # 共同关注
SRANDMEMBER prize 3 # 随机抽 3 个(不删除)
SPOP prize 1 # 随机弹 1 个(删除)
典型场景:点赞去重、标签、共同好友、抽奖。
注意:SISMEMBER 判断用它是首选,但别用 SMEMBERS 取大集合再在代码里判断——百万级集合会把内存打爆,用 SSCAN 分批。抽奖「可重复中奖」用 SRANDMEMBER,「中奖即出局」用 SPOP,别搞反。
第六步:Zset——排行榜和延时队列
有序集合,每个成员带一个 score,按 score 自动排序,这是 Redis 最有价值的类型。
ZADD rank:week 980 "用户A" 870 "用户B"
ZINCRBY rank:week 20 "用户A" # 加分
ZREVRANGE rank:week 0 9 WITHSCORES # 取前 10 名(高分在前)
ZRANK rank:week "用户B" # 查排名(从 0 开始)
ZREVRANGEBYSCORE rank:week +inf -inf LIMIT 0 10
典型场景:
- 排行榜:
ZINCRBY 累加分数,ZREVRANGE 取 TopN,ZREVRANK 查「我排第几」
- 延时队列:score 存到期时间戳,消费者用
ZRANGEBYSCORE queue 0 当前时间戳 LIMIT 0 10 捞到期任务
- 滑动窗口限流:score 存请求时间戳,先
ZREMRANGEBYSCORE 清掉窗口外的,再 ZCARD 数数量
注意:score 是 double 类型,超过 2^53 的整数会丢精度,别拿雪花 ID 直接当 score。另外 ZADD 对已存在的 member 是更新分数而非新增,做「每日新增统计」时误用会导致数据一直对不上。
小结
- String 存单值、计数、缓存、分布式锁;锁必须用
SET key val NX EX 一条命令。
- Hash 存对象、可局部更新;大 Hash 禁用
HGETALL,用 HSCAN。
- List 做最新列表和轻量队列;可靠队列请换 Stream。
- Set 做去重、标签、集合运算和抽奖;区分
SRANDMEMBER 和 SPOP。
- Zset 做排行榜、延时队列、限流;注意 score 的精度和「更新语义」。
- 通用纪律:线上禁用
KEYS *、SMEMBERS、LRANGE 0 -1 这类全量命令,一律用 SCAN 系列分批;给缓存 key 都带上过期时间。