Redis 常见数据结构有哪些,Set 与 ZSet 有何区别?
未标记
考查重点:去重集合与带分排序。Set只去重无分数排序,ZSet成员唯一并按score排序;String/Hash/List再按访问操作选
本题目录
参考答案
核心回答
Redis 常见的五种基本类型是 String、Hash、List、Set 和 ZSet,选择时主要看需要表达什么数据、支持什么操作:
String: 保存字符串或二进制值,也常用来存序列化对象、做整数计数。Hash: 保存字段到值的映射,适合按字段读取、修改对象属性。List: 保存有位置顺序、允许重复的元素,适合两端操作和顺序记录。Set: 保存无序且唯一的成员,适合去重、成员判断、交并差。ZSet: 保存唯一成员及其score,维护按分数的顺序,适合排行榜、排名和范围检索。
此外还有 Stream,以及 Bitmap、HyperLogLog、GEO 等常用能力,不能理解为 Redis 只有这五种用法。
Set 与 ZSet 都要求成员唯一,区别是 ZSet 为每个成员关联分数并维护有序访问。 Set 不维护插入顺序;ZSet 默认按 score 升序,同分时按成员的字节字典序排列。分数可以重复,同一个成员却不会因为分数不同而变成两条记录。
用什么场景区分 Set 与 ZSet
文章点赞用户可以存成 Set:成员是用户 ID,同一个用户重复加入不会增加成员数;查询是否点过赞、统计点赞人数、求两篇文章的共同点赞用户,都贴合其集合语义。
文章热度榜可以存成 ZSet:成员是文章 ID,score 是热度。需要查询排名、前若干名或某个分数范围时,ZSet 能直接按维护好的顺序查找。更新同一文章的 score 是更新原成员,不是追加一条新成员。
例如 A 得 90 分、B 得 100 分,再把 A 更新为 95 分,集合仍只有 A、B 两个成员,升序是 A、B。如果业务要求同分时按最早达分时间排名,就需要另外设计同分规则,默认字典序并不等于先到先得。
类型和底层编码有什么关系
类型是用户看到的操作语义,编码是某个对象内部的实现,同一种类型可能根据数据规模和配置采用不同编码。
以 Redis 8.6 为例,Set 可采用整数集合、listpack 或哈希表;ZSet 的小集合可用 listpack,较大的集合通常使用跳表加哈希表。跳表服务于有序定位、范围和排名,哈希表便于按成员找到分数;紧凑编码则以一定的遍历开销换取空间。
因此,不能说 Set 永远就是哈希表、ZSet 永远只有一张跳表,也不能把所有命令都写成 O(1) 或 O(log n)。例如较大有序集合的范围查询还要返回 M 个元素,成本通常包含 O(M);一次返回全部成员、做大集合交并差,仍可能产生较高的执行和网络成本。
追问:ZSet 能直接当过期集合或可靠队列吗
可以用时间戳作 score 表达时间范围,并按业务清理超时成员;但分数本身不会触发自动删除。对整个键设置 TTL,与按 score 清理某些成员是两件事。
单个 Set、ZSet 还可能持续增长为大键。应按活动或时间窗口规划保留范围,限制一次取回的数量,选择适合的扫描、范围读取和清理方式;仅给一个不断续期的总键设置 TTL,不一定能约束内部成员增长。
同样,按时间取出一批任务不自动具备 MQ 的确认、失败恢复和重复处理语义;这些需要另外设计。容器内一次添加是原子的,也不代表“先查成员再执行业务”这样的多步操作整体原子。
对应教程
- 《从零开始学 AI Agent》第 16 章:记忆与对话历史,5.2.4 节:通过 TYPE、LRANGE 观察按会话保存的消息列表,回看 List 如何表达顺序历史;Set 与 ZSet 的去重、排序和内部编码在本文中进一步展开。
参考资料
- 国内:JavaGuide:Redis 基本数据结构:用于整理五种基本类型、常用操作和场景,区分 List 的顺序与 Set 的唯一成员语义。
- 国内:doocs:Redis 数据类型和使用场景:用于说明对象字段、顺序列表、集合去重和分数排名各自适合的用途。
- 国内:小林 coding:Redis 常见数据类型和应用场景:用于解释 Set 的集合运算成本,以及 ZSet 的紧凑编码、跳表与哈希表分工和排行榜场景。
- 国外:Redis:Redis sets:用于核对成员唯一、无序、重复添加不增加条目的语义和集合操作范围。
- 国外:Redis:Redis sorted sets:用于核对 score 排序、同分成员顺序、已有成员更新及范围、排名操作的语义。



