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 的确认、失败恢复和重复处理语义;这些需要另外设计。容器内一次添加是原子的,也不代表“先查成员再执行业务”这样的多步操作整体原子。

对应教程

参考资料

相关面经

4 篇

腾讯

后端开发工程师
实习一面
查看原面经 →
Redis 的 `Set` 底层是怎么实现的?

车300

Java 开发工程师
实习
查看原面经 →
Redis 常见数据结构?
Set 和 ZSet 的区别?

飞轮数据

Go 后端开发工程师
二面
查看原面经 →
你对 Redis 了解多少?

字节跳动

后端开发工程师
一面
查看原面经 →
Redis 的数据类型有哪些?

相关题目

4 题