redis常见数据结构及其编码方式

文章目录

  • 1.引言
  • 2.常见数据结构
  • [3.核心认知:数据类型与编码方式的 "分离设计"](#3.核心认知:数据类型与编码方式的 “分离设计”)
    • [3.1 复杂度不变,实现动态适配](#3.1 复杂度不变,实现动态适配)
    • [3.2 编码方式的 "切换触发条件"](#3.2 编码方式的 “切换触发条件”)
  • [4.查看底层编码 ------object encoding](#4.查看底层编码 ——object encoding)
  • [5. 常用数据类型的编码优化逻辑](#5. 常用数据类型的编码优化逻辑)
    • [5.1 String(字符串):3 种编码适配不同场景](#5.1 String(字符串):3 种编码适配不同场景)
    • [5.2 Hash(哈希):压缩列表 vs 哈希表](#5.2 Hash(哈希):压缩列表 vs 哈希表)
    • [5.3 List(列表):压缩列表 vs 双向链表](#5.3 List(列表):压缩列表 vs 双向链表)
    • [5.4 Set(集合):整数集合 vs 哈希表](#5.4 Set(集合):整数集合 vs 哈希表)
    • [5.5 ZSet(有序集合):压缩列表 vs 跳表](#5.5 ZSet(有序集合):压缩列表 vs 跳表)
  • 6.小结

1.引言

提到 Redis 的数据结构,多数人会立刻想到 String、Hash、List 等常用类型。但鲜有人知的是:Redis 在底层实现时,并不会严格绑定某一种数据结构 ------ 为了兼顾性能与空间效率,它会根据数据的实际特征动态选择 "编码方式"。这种 "表面类型与底层编码分离" 的设计,正是 Redis 能在复杂场景下保持高效的核心原因之一。本文将带你拆解 Redis 数据结构的编码优化逻辑,看懂 "数据结构背后的真相"。

2.常见数据结构

当前版本的redis支持10个数据类型,其中5个比较常用

3.核心认知:数据类型与编码方式的 "分离设计"

3.1 复杂度不变,实现动态适配

Redis 的设计坚守一个基本原则:无论底层采用何种编码,用户操作数据结构的时间复杂度、空间复杂度都与抽象类型承诺一致。

例如,Hash 类型对外承诺 "键值对的增删改查为 O (1)",底层无论用 "压缩列表" 还是 "哈希表" 实现,都能保证这一复杂度;但两种编码的空间占用、操作效率在不同数据规模下差异巨大 ------ 这正是编码优化的价值所在。

3.2 编码方式的 "切换触发条件"

编码方式的切换由 Redis 自动完成,无需用户干预,触发条件通常与 "数据量大小" 或 "元素特征" 相关:

  • 小数据量场景:优先选择 "空间紧凑" 的编码(如压缩列表),节省内存;
  • 大数据量 / 高频操作场景:自动切换到 "操作高效" 的编码(如哈希表、跳表),保证性能。

这种 "自适应切换" 让 Redis 既能高效存储海量小数据,又能应对大数据的高频访问,实现 "内存与性能的平衡"。

4.查看底层编码 ------object encoding

要验证 Redis 的编码优化逻辑,最直接的方式是使用object encoding命令 ------ 它能返回指定 Key 对应的 Value 的实际底层编码。

  • 语法:object encoding key

5. 常用数据类型的编码优化逻辑

5.1 String(字符串):3 种编码适配不同场景

String 是 Redis 最基础的类型,底层支持 3 种编码,核心围绕 "字符串长度" 与 "是否可修改" 优化:

编码类型 适用场景 核心优势
int 字符串为 64 位以内的整数(如set num 123) 直接用整数存储,比字符串格式更省内存
embstr 字符串长度≤44 字节(默认)的短字符串 字符串与 Redis 对象元数据存储在同一块内存,减少内存碎片
raw 字符串长度 > 44 字节的长字符串 单独存储字符串内容,避免元数据与长字符串占用连续内

示例:

bash 复制代码
127.0.0.1:6379> set num 123456
OK
127.0.0.1:6379> object encoding num
"int"  # 整数编码

127.0.0.1:6379> set short_str "hello redis"  # 11字节
OK
127.0.0.1:6379> object encoding short_str
"embstr"  # 短字符串编码

127.0.0.1:6379> set long_str "this is a very long string...(超过44字节)"
OK
127.0.0.1:6379> object encoding long_str
"raw"  # 长字符串编码

5.2 Hash(哈希):压缩列表 vs 哈希表

Hash 用于存储 "键值对集合",编码切换的核心是 "键值对数量" 与 "元素大小":

编码类型 适用场景 核心优势
ziplist(压缩列表) 键值对数量≤512 个(默认),且每个键 / 值长度≤64 字节 连续内存存储,无哈希表的指针开销,极省内存
hashtable(哈希表) 键值对数量 > 512 个,或任一键 / 值长度 > 64 字节 支持 O (1) 的增删改查,适合高
  • 优化逻辑:小哈希表用压缩列表节省内存(如存储用户基本信息,字段少且短);当数据增长后,自动切换到哈希表保证操作效率(如存储商品的多维度属性,字段多且长)。

5.3 List(列表):压缩列表 vs 双向链表

List 是 "有序元素集合",编码优化围绕 "元素数量" 与 "长度":

编码类型 适用场景 核心优势
ziplist(压缩列表) 元素数量≤512 个(默认),且每个元素长度≤64 字节 连续内存存储,遍历效率高,内存占用少
linkedlist(双向链表) 元素数量 > 512 个,或任一元素长度 > 64 字节 支持高效的头部 / 尾部插入删除,适合大列表
  • 注意:Redis 3.2 版本后引入quicklist(快速列表)编码,它是 "压缩列表 + 双向链表" 的混合结构 ------
    将大列表拆分为多个小压缩列表,既保留压缩列表的内存优势,又解决长列表的遍历效率问题,目前已成为 List 的默认编码。

5.4 Set(集合):整数集合 vs 哈希表

Set 是 "无序、唯一元素集合",编码优化针对 "元素是否为整数":

编码类型 适用场景 核心优势
intset(整数集合) 所有元素均为 64 位以内的整数(如sadd nums 1 2 3) 按整数大小有序存储,支持二分查找,内存占用极低
hashtable(哈希表) 包含非整数元素(如add names zhangsan lisi) 用哈希表的键存储集合元素(值为 null),支持 O (1) 的存在性判断

5.5 ZSet(有序集合):压缩列表 vs 跳表

ZSet 是 "按分数排序的唯一元素集合",编码优化围绕 "元素数量" 与 "长度":

编码类型 适用场景 核心优势
ziplist(压缩列表) 元素数量≤128 个(默认),且每个元素长度≤64 字节 按分数有序存储,连续内存,省空间
skiplist(跳表) 元素数量 > 128 个,或任一元素长度 > 64 字节 结合跳表与哈希表,支持 O (logN) 的排序与查找,适合大数据排序场景(如排行榜)

6.小结

Redis 的数据结构设计,藏着 "平衡取舍" 的工程智慧:对外提供简单统一的抽象类型,让开发者无需关心底层细节;对内通过动态编码优化,在不同场景下实现 "内存与性能的最优解"。

核心要点可归纳为三点:

  1. 分离设计:数据类型是 "抽象接口",编码方式是 "底层实现",复杂度承诺不变,实现动态适配;
  2. 工具关键:object encoding命令是窥探底层的窗口,建议在开发调试时多使用,建立 "类型 - 编码" 的对应认知;
  3. 场景适配:小数据用 "紧凑编码"(压缩列表、整数集合)省内存,大数据用 "高效编码"(哈希表、跳表)保性能,切换由 Redis 自动完成。
相关推荐
im_AMBER3 小时前
数据结构 01 线性表
数据结构·学习
_码力全开_3 小时前
Python从入门到实战 (14):工具落地:用 PyInstaller 打包 Python 脚本为可执行文件
开发语言·数据结构·python·个人开发
tpoog3 小时前
[C++项目框架库]redis的简单介绍和使用
开发语言·c++·redis
Keying,,,,4 小时前
秋招算法记录 | 排序算法整理 | 直接选择、直接插入、冒泡、快排、希尔排序
数据结构·python·算法·排序算法
仰泳的熊猫5 小时前
LeetCode:496. 下一个更大元素 I
数据结构·c++·算法·leetcode
铜峰叠翠6 小时前
Redis安装配置
数据库·redis·缓存
Craaaayon7 小时前
【数据结构】二叉树-图解深度优先搜索(递归法、迭代法)
java·数据结构·后端·算法·leetcode·深度优先
高山有多高7 小时前
C语言实战项目:贪吃蛇(2)
c语言·开发语言·数据结构·c++·算法·游戏·游戏设计
Miraitowa_cheems11 小时前
LeetCode算法日记 - Day 55: 子集、找出所有子集的异或总和再求和
数据结构·算法·leetcode·决策树·深度优先·剪枝