当前位置: 首页 > news >正文

hash 与 zset 空间占用对比分析

一、问题背景

Redis 中相同数量的数据,使用 hash 与 zset 存储时空间占用差异究竟有多大?这是面试中常见的高频考点,核心考察点在于ziplist vs skiplist vs dict三种底层数据结构的空间复杂度。


二、数据结构选择规则

Redis 根据节点数量动态选择底层数据结构,具体阈值如下:

存储结构ziplist 阈值dict/skiplist 阈值
hash节点数 <= 512节点数 > 512
zset节点数 <= 128节点数 > 128

核心结论:

  • 节点数 <= 128 时,hash 和 zset 均使用 ziplist,空间占用相同
  • 节点数 129~512 时,hash 使用 ziplist,zset 使用 skiplist
  • 节点数 > 512 时,hash 使用 dict,zset 使用 skiplist + dict

三、hash 内部数据结构

3.1 ziplist(压缩列表)

当 hash 节点数 <= 512 时采用,本质是一段连续的内存块:

+----------+----------+----------+----------+----------+ | prevlen | encoding | data | prevlen | ... | +----------+----------+----------+----------+----------+

空间占用特点:

  • 紧凑存储,无额外指针开销
  • prevlen 字段使用变长编码(1-5字节)
  • 新增/删除操作可能触发级联更新
3.2 dict(字典)

当 hash 节点数 > 512 时采用,本质是哈希表

struct dict { dictht table[2]; // 两个哈希表,支持渐进式 rehash long rehashidx; // rehash 进度,-1 表示未进行 long iterators; // 当前迭代器数量 };

空间占用特点:

  • 每个 key-value 对额外占用一个 dictEntry 指针
  • 负载因子 > 1 时触发扩容,空间换时间
  • 存在指针开销,约 16-24 字节/条目

四、zset 内部数据结构

4.1 ziplist(压缩列表)

当 zset 节点数 <= 128 时采用,有序存储:

+----------+----------+----------+----------+----------+ | score | member | score | member | ... | +----------+----------+----------+----------+----------+

空间占用特点:

  • score 和 member 交替存储
  • 紧凑无指针开销
  • 查询需要遍历,时间复杂度 O(n)
4.2 skiplist + dict(跳跃表 + 字典)

当 zset 节点数 > 128 时采用,这是zset 的核心结构

struct zset { dict *dict; // member -> score 字典,O(1) 查询 skiplist *zsl; // 跳跃表,按 score 有序 };

为什么需要 dict?

  • skiplist 查询 member 需要 O(n),加入 dict 后可直接 O(1) 获取 score
  • dict 和 skiplist 同时存储 member,数据冗余

五、skiplist 空间占用详解

5.1 数据结构定义
structskipListNode{doublescore;// 分数,8字节robj*obj;// 成员对象指针,8字节intbackward;// 后退指针,4字节(压缩指针)structskipListLevel{skipListNode*forward;// 前向指针,8字节unsignedintspan;// 跨度,4字节}level[];// 柔性数组,层数随机};
5.2 层数计算公式

节点层数根据以下规则随机生成:

// Redis 源码中的层高计算intrandomLevel(void){intlevel=1;while(random()<(1/4))// 1/4 概率继续增加层数level++;returnlevel;}

层数期望推导:

层数概率累积概率
13/475%
23/1618.75%
33/644.6875%
43/2561.171875%

期望层数 E = 1 + 1/4 + 1/16 + 1/64 + … =4/3 层

平均层数约为 1.33 层

5.3 空间占用公式

对于 n 个节点的 skiplist:

节点总空间 = n × (基础字段 + 指针开销)

基础字段(每个节点固定):

  • score: 8 字节
  • obj 指针: 8 字节
  • backward 指针: 4 字节

每层开销(平均 1.33 层):

  • forward 指针: 8 字节 × 1.33 ≈ 10.64 字节
  • span: 4 字节 × 1.33 ≈ 5.32 字节

总计:约 32-36 字节/节点(不含 dict)


六、空间对比分析

6.1 阈值区间对比
节点数范围hashzset结论
<= 128ziplistziplist空间相同
129~512ziplistskiplistzset 更占空间
> 512dictskiplist + dictzset 更占空间
6.2 定量空间估算

假设存储 1000 个节点(key + value 各 16 字节):

数据结构每个节点开销1000节点总空间
hash (dict)~48 字节~48KB
zset (skiplist)~32 字节~32KB
zset (dict+skiplist)~80 字节~80KB

关键结论:zset 在使用 skiplist + dict 时,空间占用约为 hash 的 1.5~2 倍


七、面试追问 FAQ

问题回答要点
Q: skiplist 为什么用空间换时间?多层索引实现二分查找,平均 O(log n) 而非 ziplist 的 O(n)
Q: dict 和 skiplist 存储相同 member 是否冗余?是,但保证 O(1) 查到 score 的同时维持有序性
Q: 层高公式中 1/4 的物理意义?控制空间利用率,层数期望常数(4/3),避免指数增长
Q: hash 超过 512 为什么不转 skiplist?hash 需要的是 O(1) 查找,有序性不是核心需求
Q: ziplist 触发条件为何 zset 比 hash 更早?zset 需要维护有序性,节点数多时遍历成本高,更早切换 skiplist

八、相关题目

题目考察点
Redis zset 为什么同时用 dict 和 skiplist?数据结构设计原理
skiplist 层高为什么是随机而非常数?空间与时间平衡
Redis 为什么不用 B+ 树替代 skiplist?实现复杂度 vs 场景需求
hash 何时从 ziplist 转为 dict?阈值配置原理

九、总结

对比维度hashzset
少量数据 (<=128)ziplist,紧凑ziplist,紧凑
中等数据 (129~512)ziplistskiplist,更占空间
大量数据 (>512)dictskiplist + dict,最占空间
查找时间复杂度O(1)O(1) score 查询
有序性score 有序

核心结论:zset 在数据量大时空间占用显著高于 hash,根源在于 skiplist 的多层索引结构 + dict 冗余存储。这是典型的空间换时间设计权衡。


根据零声教育教学写作https://github.com/0voice

http://www.jsqmd.com/news/860420/

相关文章:

  • 对比按需计费与 Token Plan 套餐哪种方式更适合长期项目
  • 【本地部署】告别高昂 API 费用:使用 Ollama 本地部署视觉模型(LlaVA/Qwen-VL)实战
  • 南昌购宠避坑指南:5 家靠谱实体门店实测推荐 - 资讯纵览
  • 终极指南:如何使用Robomongo免费管理MongoDB数据库
  • XBOX360 KINECT体感游戏合集109个
  • 普宁近视防控眼镜哪家做|孩子该选罗敦司得还是豪雅新优学 - 品牌观察
  • 别再只会用ls了!用C语言stat()函数深入挖掘Linux文件隐藏信息(附完整代码)
  • 从分账到风控:三角洲游戏护航平台俱乐部接单平台游戏电竞护航陪玩源码系统小程序 - 壹软科技
  • Tftpd32/Tftpd64深度使用:除了传文件,它的DHCP、Syslog服务器功能怎么玩?
  • Redis 实现限流功能的几种方法
  • Yokogawa SR1030B62伺服执行器控制器
  • 如何免费获取百度文库文档:三步实现纯净打印保存的实用技巧
  • 江苏储能电池箱定制企业排行 品质保障实力盘点 - 奔跑123
  • 告别固定亮度:在普冉PY32F003上实现PWM呼吸灯,从硬件定时器配置到软件平滑曲线调光
  • 告别命令行!用mqtt-spy这个开源神器,5分钟搞定MQTT消息调试(附保姆级配置流程)
  • Prometheus标签操作实战:从label_replace到group_left,搞定K8s监控数据关联与聚合
  • 精细化网格治理!地理空间与网格化技术融合
  • 从知网AI率99%降至3%?2026年5月降AI率工具全网最全红黑榜 - 我要发一区
  • 生产线员工智能排班系统,落地步骤与人力优化方案:基于实在Agent与TARS大模型的工业级实现
  • IDEA插件Show Comments隐藏玩法:自定义标签和过滤器,打造你的专属代码审查助手
  • Tidal-Media-Downloader:Python开源音乐下载工具深度解析与实战应用
  • 制造业生产安全隐患智能识别系统落地指南 —— 结合企业级Agent构建国产安全闭环防御体系
  • 手把手教你用vulkaninfo和ldd命令,精准定位Ubuntu下UE游戏Vulkan启动失败的根本原因
  • 临近毕业降AI率保姆级教程:嘎嘎降3分钟,知网AI率5%以下 - 我要发一区
  • 启XX辰-头部安全公司面试提问
  • 2026电梯物联网大数据机构排行榜高频疑问全解答 - 资讯纵览
  • Redis 为什么是单线程?为什么这么快?
  • 从灰度图到霓虹渐变,Midjourney色调分离全流程拆解,含12组可复用prompt模板+权重对照表
  • 从24V开关电源到芯片供电:手把手教你搞定差模电感选型与PCB布局(附计算过程)
  • 3D格式转换神器:如何用stltostp轻松实现STL到STEP的无缝转换