数据库与缓存12 分钟阅读更新于 2026-07-30

Redis 五种基础数据类型怎么选:String、Hash、List、Set、Zset

Redis 数据类型章节,讲清 String、Hash、List、Set、Zset 的结构特点、底层实现线索和典型业务场景,帮助在缓存、计数、购物车、消息队列、点赞、排行榜中选对数据结构。

相关工具

先看业务形态,再选数据结构

Redis 好用,很大一部分原因不只是快,而是它给了多种贴近业务的数据结构。文中把常见类型列成五种:String、Hash、List、Set、Zset。它们都能存数据,但适合的业务形态不一样。选错了,后面代码会很绕;选对了,很多操作可以直接用 Redis 命令完成。

学习 Redis 数据类型时,不建议从命令表开始背。更好的顺序是先问业务数据长什么样:是一个简单值,还是一个对象?是要保持顺序,还是要去重?是普通集合,还是需要按分数排序?答案不同,对应的数据结构就不同。

这篇会按业务场景来讲五种基础类型:String 适合简单值、缓存对象、计数和锁;Hash 适合对象字段;List 适合顺序列表和队列;Set 适合去重和集合运算;Zset 适合排行榜和带分数的排序列表。

Redis 五种基础数据类型怎么选的图解,包含 String、Hash、List、Set、Zset 的适用场景:缓存对象、计数、购物车、消息队列、点赞、共同关注、排行榜等
Redis 五种基础数据类型选型

不要只按命令选类型,先判断数据是否是值、对象、顺序列表、去重集合,还是带分数排序的集合。

String:最基础,也最常用

String 是 Redis 里最基础的数据类型。文中说,String 底层主要使用 SDS,也就是简单动态字符串。它可以用来缓存整个对象的 JSON,也可以做计数、分布式锁和共享 Session 信息。

缓存对象是最常见的用法。比如商品详情、用户资料、配置项,可以把对象序列化成 JSON 后放入 String。应用读取时先查 Redis,命中就解析返回,未命中再回源 MySQL。这里要注意,String 存 JSON 很方便,但如果对象里某些字段频繁变化,每次都改整段 JSON 可能不够细。

计数也适合 String。已有内容提到,Redis 处理命令是单线程,所以执行命令的过程具有原子性,String 适合访问次数、点赞数、转发数、库存数量等场景。相比应用先读再写,直接用 Redis 的原子递增命令更不容易出现并发覆盖。

String 还能做锁和 Session

分布式锁也常从 String 讲起。文中提到可以利用 `SETNX` 命令。它的含义是 key 不存在时才设置成功。多个服务实例同时抢同一把锁,只有一个能成功写入这个 key,其余实例拿到失败结果。

不过生产里的锁不能只写 `SETNX` 就完事。还要考虑过期时间,避免持锁服务崩溃后锁永远不释放;释放锁时要校验锁的拥有者,避免误删别人的锁;锁时间不够时可能需要续期。String 提供了原子入口,完整可靠性仍要靠业务流程补齐。

共享 Session 也是 文中提到的场景。多台应用服务器如果把登录态存在各自内存里,用户请求打到不同机器时可能出现状态丢失。把 Session 放到 Redis,多台服务器都查同一个位置,登录态就能跨实例共享。

Hash:对象字段更适合拆开存

Hash 可以理解成一个 key 下面有多个 field-value。文中说,Hash 底层由压缩列表或哈希表实现;在 Redis 7.0 中,压缩列表被 listpack 替代。它的典型场景是缓存对象和购物车。

如果对象整体变化不多,用 String 存 JSON 就很简单。但如果对象中某些字段频繁变化,比如用户资料里的昵称、头像、积分,或者商品对象里的库存展示值,用 Hash 把字段拆开,更新会更自然。你可以只改某个 field,不必每次读出整个 JSON、修改、再整体写回。

购物车是 Hash 的经典例子。文中写得很清楚:以用户 ID 为 key,商品 ID 为 field,商品数量为 value,正好构成购物车的三个要素。用户加购、改数量、删除商品,都可以围绕 field 操作。相比把整个购物车数组塞成一个 JSON,Hash 更贴近这个业务模型。

List:有顺序的列表和简单队列

List 适合有顺序的数据。文中说,List 类型底层曾由双向链表或压缩列表实现;Redis 3.2 之后使用 quicklist 替代;Redis 7.0 中压缩列表被 listpack 替代。这里不用一开始就背版本细节,先记住:List 关心顺序,能从两端插入和弹出。

已有例子了两个场景。一个是按顺序显示点赞好友信息,如果取消点赞,就移除对应好友。另一个是消息队列:生产者可以用 `LPUSH` 从左边插入数据,消费者用 `BRPOP` 从右边阻塞式取出数据,形成左进右出的队列。

List 做队列适合简单场景,但如果需要更可靠的消息语义,比如消费组、历史消息、离线重连后继续读取,后面会用到 Stream。资料 在扩展类型里也提到,Stream 是 Redis 专门为消息队列设计的数据类型。

Set:去重和集合运算

Set 是集合,最核心的特点是去重。文中说,Set 底层由哈希表或整数集合实现:如果集合元素都是整数且数量较少,可能使用整数集合;否则使用哈希表。业务上,你可以先把它理解成“不允许重复成员的一组值”。

点赞适合 Set。比如 key 是文章 ID,value 是用户 ID。用户点赞时加入集合,取消点赞时移除。因为 Set 天然去重,同一个用户不会重复点赞。判断用户是否点过赞,也可以直接查成员是否存在。

共同关注也适合 Set,因为 Set 支持交集运算。一个用户关注的公众号或好友 ID 放在一个集合里,两个用户的集合取交集,就能得到共同关注。抽奖活动也适合 Set,因为中奖用户放进集合后,同一个用户不会中奖两次。

Zset:带分数的有序集合

Zset 是 Sorted Set,有序集合。文中说,Zset 可以根据元素权重排序,权重值由业务自己决定。比如可以按插入时间、播放量、积分、销量、热度分作为 score。

当你需要展示最新列表、排行榜,而且数据更新频繁或需要分页时,可以优先考虑 Zset。文中提到的典型场景就是排行榜,例如学生成绩排名、游戏积分排行、视频播放排名、电商商品销量排名。

Zset 的关键不是“有序”,而是“按 score 有序”。普通 Set 只关心有没有某个成员,Zset 还关心这个成员排在什么位置。需要 TopN、范围查询、按分数分页、实时排行时,Zset 往往比 MySQL 排序查询更适合承接高频读取。

扩展类型补齐特殊场景

资料 在五种基础类型后,还提到了 BitMap、HyperLogLog、GEO、Stream。它们不是这篇的重点,但可以先知道各自解决什么问题。

BitMap 用 bit 存储,适合数据量大、状态只有两种的统计场景,比如签到统计、判断用户登录态。HyperLogLog 用于基数统计,文中提到它基于概率,标准误算率约 0.81%,优点是输入元素数量很大时,占用内存仍然固定且很小,适合百万级网页 UV 计数这类场景。

GEO 用来存地理位置信息,底层由 Zset 实现,通过 GeoHash 把经纬度转换成 Zset 权重分数。Stream 则是 Redis 专门为消息队列设计的数据类型,支持自动生成全局唯一消息 ID,也支持消费组形式消费数据。

别用一个类型硬扛所有需求

实际应用中,最常见的错误是把所有东西都塞成 String JSON。这样开始很快,但后面字段更新、局部读取、并发修改、集合运算、排序分页都会变麻烦。Redis 给出多种数据结构,就是为了让数据形态贴近操作方式。

如果是一个完整对象,且通常整体读取,String 很合适;如果对象字段经常局部修改,Hash 更自然;如果要按插入顺序处理,List 可以考虑;如果要去重或做交集,Set 更合适;如果要排序、排行、按分数取范围,就看 Zset。

选型时还要考虑数据量、过期时间、是否需要持久化、是否能重建。Redis 是内存系统,结构选得再好,也不能忽略容量和淘汰策略。数据类型是第一步,生命周期设计是第二步。

面试和实战可以这样回答

如果被问 Redis 有哪些常见数据类型,可以先答五种:String、Hash、List、Set、Zset。然后别停在名字上,顺手带出场景:String 用于缓存对象、计数、分布式锁和 Session;Hash 用于对象字段和购物车;List 用于顺序列表和简单队列;Set 用于点赞、共同关注、抽奖;Zset 用于排行榜和按分数排序。

如果追问底层实现,可以补充 文中的线索:String 主要基于 SDS;List 在 Redis 3.2 后由 quicklist 实现,Redis 7.0 中 listpack 替代压缩列表;Set 可以由整数集合或哈希表实现;Hash 可以由 listpack 或哈希表实现;Zset 可以由压缩列表/listpack 或跳表实现。

真正写业务代码时,则回到一句话:先看业务形态,再选数据结构。Redis 的优势不是把所有数据都变成缓存,而是让高频状态用更合适的结构表达出来。

常见问题

Redis String 适合哪些场景?

适合缓存对象 JSON、计数、分布式锁入口、共享 Session 等简单值或整体读写场景。

Hash 和 String 存对象有什么区别?

String 通常把对象整体序列化后存储,适合整体读写;Hash 可以拆成多个 field-value,适合对象字段经常局部读取或修改的场景。

List 和 Stream 都能做消息队列,怎么区分?

List 可以做简单队列,例如 LPUSH + BRPOP;Stream 是 Redis 专门为消息队列设计的类型,支持消息 ID、消费组和历史消息读取,更适合可靠队列场景。

Zset 为什么适合排行榜?

Zset 给每个成员绑定 score,并按 score 排序。需要 TopN、按分数范围查询、实时排行和分页展示时,Zset 比普通 Set 更适合。

MySQL 与 Redis

继续阅读

返回专题