说明:Redis 底层是 key-value ,key 都是字符串;区别在于 value 的数据类型 。 常用 8 种:String、List、Set、Hash、SortedSet (ZSet)、Bitmap、HyperLogLog、Geo; 新增:Stream(5.0+,消息队列)。
1. String 字符串(最基础,必掌握)
底层不是单纯字符串,是 SDS;可以存:普通字符串、数字、序列化 JSON。 命令:set / get / mset / mget / incr / incrby / decr / expire
✅ 适用场景:
- 缓存:热点数据缓存(用户信息、商品基础信息、首页配置、字典数据),减轻 DB 压力
- 计数器 :阅读量、点赞数、访问次数、接口限流计数(
incr原子自增) - 分布式 ID:incr 生成全局自增 ID
- 分布式锁 :
setnx + expire(基础版本,生产一般用 Redisson) - 临时验证码、token、短信验证码,设置过期时间
- 简单限流:固定窗口限流
注意:value 最大 512M;存对象建议 JSON 序列化,复杂对象优先考虑 Hash。
2. Hash 哈希(key -> field-value,类似 Java Map<String,Object>)
命令:hset / hget / hgetall / hmget / hincrby / hexists 结构:key:{field1:v1, field2:v2}
✅ 适用场景:
- 对象缓存 :用户信息、商品信息。只需要更新其中一个字段(比如用户头像、手机号),不用像 String 一样全量序列化覆盖,
hset单独改 field,更省带宽。 - 购物车:key=userId,field=skuId,value = 数量
- 配置项分组缓存:一组相关配置放同一个 hash
- 统计维度分组计数:比如某个活动下各个子项的分数
对比 String 存 JSON:
- 只改个别字段 → Hash 更香
- 经常一次性读取整个对象 → String (JSON) 更合适(hgetall 会遍历所有 field,field 多的时候慢)
3. List 列表(双向链表,有序、可重复)
命令:lpush / rpush / lpop / rpop / lrange / ltrim 特点:左边、右边进出;有序,允许重复元素,可以做分页。
✅ 适用场景:
- 简单消息队列(生产者 lpush,消费者 rpop) ⚠️ 缺点:没有 ack、没有消费确认、消费者挂了消息丢了;正式 MQ 不要用这个,仅临时简单场景
- 消息栈、最新消息列表:最新评论、最新操作日志(lpush,lrange 分页查看)
- 排行榜(简单时序)、滚动列表
- 限流漏斗、固定长度队列:搭配 ltrim 保留最近 N 条数据
特点:头尾操作极快;中间下标访问慢,不要用 list 做随机查询。
4. Set 集合(无序、不可重复)
命令:sadd / srem / smembers / sismember / sinter(交集) / sunion(并集) / sdiff(差集)
✅ 适用场景:
- 去重:点赞集合(用户 ID 放进 set,一个用户只能点赞一次,sismember 判断是否已点赞)
- 交集、并集计算 :
- 共同好友、共同关注
- 标签筛选:喜欢标签 A AND 标签 B 的用户
- 抽奖 :随机抽取
srandmember,不重复中奖 - 黑名单、白名单
重点:天然去重;无序;适合做存在性判断、集合运算。
5. ZSet Sorted Set 有序集合(最强大)
每个元素:member + score(分数,double),不重复 member,按 score 排序 命令:zadd / zrange / zrevrange / zrank / zscore / zincrby / zrem
✅ 适用场景(面试高频):
- 各种排行榜 :热度榜、销量榜、积分排行榜、直播间贡献榜
- score = 热度值,zrevrange 倒序取 TopN
- 延时队列(简易版):score = 时间戳,轮询取到期任务(生产复杂延时任务推荐 Redisson 延迟队列)
- 带权重的有序列表
- 范围查询:score 区间筛选(比如积分 100~1000 的用户)
和 Set 区别:多了 score,自带排序;和 List 区别:List 是插入顺序,ZSet 是自定义分数排序。
6. Bitmap 位图(String 底层实现,bit 操作)
命令:setbit / getbit / bitcount / bitop 本质:把 string 当成一串二进制位,一个 bit 代表一个标记,极度省内存
✅ 适用场景:
- 签到统计:key = 用户,bit 位 = 日期,bitcount 统计当月签到天数
- 活跃用户统计:key = 日期,bit 下标 = userId,快速统计当日活用户、多天用户交集
优势:百万级用户只需要十几 MB 内存
7. HyperLogLog(基数统计,估算,有误差)
命令:pfadd / pfcount / pfmerge 作用:统计不重复元素的数量(基数),不存原始数据,空间极小;误差 0.81% 左右
✅ 适用场景:
- UV 统计(独立访客):页面、接口每日 UV,不需要精确值,允许微小误差
❌ 不能用在要求精准计数场景(比如订单数);PV 直接 incr (String)
8. Geo 地理位置(Redis3.2+)
命令:geoadd / geohash / geopos / geodist / georadius 存储:经纬度,底层是 ZSet 实现
✅ 适用场景:
- 附近的人、附近门店、附近骑手,根据坐标查询指定半径范围内数据
注意:只适合简单 LBS;复杂地图业务一般单独 GIS 引擎。
9. Stream 流(Redis5.0,专门的消息队列)
命令:xadd / xread / xgroup / xack 特点:消息持久化、消费者组、ack 确认、消息回溯、支持多消费组
✅ 适用场景: Redis 原生可靠消息队列,异步通知、削峰。 对比 List:有 ack、消息不丢、可以重试、消费组负载均衡。 ⚠️ 依然不如 RocketMQ/RabbitMQ,适合项目内部轻量异步,不适合超大吞吐事务消息。
📋 一张速查表(方便你记忆)
表格
| 类型 | 特征 | 核心场景 |
|---|---|---|
| String | 简单 k-v,支持自增 | 缓存、计数器、验证码、分布式锁 |
| Hash | field-value,分组 | 对象缓存、购物车、局部更新字段 |
| List | 有序可重复,双向链表 | 最新消息、简易队列、时序列表 |
| Set | 无序去重,支持交并差 | 点赞、共同好友、黑名单、抽奖 |
| ZSet | 按 score 排序,member 唯一 | 排行榜、延时任务、范围排序 |
| Bitmap | bit 标记,超省内存 | 签到、日活标记 |
| HyperLogLog | 基数估算、低误差 | UV 独立访客统计 |
| Geo | 经纬度坐标 | 附近门店、附近人 |
| Stream | 消息队列、消费组 + ack | 轻量可靠异步消息 |
🎯 项目选型核心思路(面试加分)
- 只是存一个值、计数、全局缓存 → String
- 一个对象,经常改其中几个字段 → Hash
- 需要去重 + 判断是否存在 + 集合运算 → Set
- 需要排序、TopN、排行榜 → ZSet
- 签到、大量布尔标记,要省内存 → Bitmap
- 估算 UV,不要精确值 → HyperLogLog
- 经纬度附近查询 → Geo
- 想在 Redis 里做可靠 MQ → Stream
📌 补充面试高频追问(顺带背)
- Q:什么时候不用 Hash,用 String 存 JSON? A:大部分场景一次性读取整个对象、字段非常多,hgetall 开销大,直接 String 序列化 JSON 更好。
- Q:ZSet 和 List 做排行榜区别? A:List 是插入顺序;ZSet 可以动态修改 score,自动重排,适合热度实时变化的榜单。
- Q:HyperLogLog 为什么不能精确统计? A:概率算法,牺牲精度换极低内存,只适合 UV 这种允许少量误差的场景。
🧠 配套速记口诀(给你)
String 缓存计数锁,Hash 对象购物车;
List 时序简易队,Set 去重交集合;
ZSet 排行延时活,Bitmap 签到省得多;
HLL 估 UV,Geo 寻近客;
Stream 消息 ack 托。