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

【Redis】5个基本数据类型

Redis 提供 5 大基本数据类型:String(字符串)、List(列表)、Set(集合)、Hash(哈希)、Zset(有序集合)。其底层实现会根据数据特征智能切换数据结构,以达到性能与内存的最优平衡。

0、底层数据结构简介

  1. 压缩列表 (Ziplist):早期使用的紧凑结构,但因存储“前一项长度”而存在连锁更新风险,修改一个元素可能引发后续元素的内存重排。
  2. 列表包 (ListPack):Redis 7.0 引入,是 Ziplist 的优化版。它将“长度信息”放在条目末尾,且只记录自身长度,彻底解决了连锁更新问题
  3. 哈希表 (HashTable):使用渐进式 rehash进行扩容。内部维护两个哈希表(ht[0]ht[1]),扩容时逐步将ht[0]的数据迁移到更大的ht[1]。期间,新写入的数据直接进入ht[1],查找时会同时检查两个表。迁移完成后释放ht[0],并将ht[1]设置为新的主表。

一、String

String 的底层是SDS (Simple Dynamic String)。SDS 有 5 种类型(sdshdr5/8/16/32/64),根据字符串长度自动选择,以优化内存。

structsdshdr{intlen;// 字符串实际长度intalloc;// 分配的总空间charbuf[];// 存储数据的柔性数组unsignedcharflags;// 标识 SDS 类型};

核心特点:

  1. 二进制安全:不依赖\0判断结尾,可存储任意二进制数据(如图片、序列化对象)。为了兼容 C 标准库函数,SDS 末尾仍会添加\0,但这不影响其二进制安全性。
  2. O(1) 获取长度:直接读取len字段。
  3. 动态扩容:写入前检查剩余空间,不足时自动扩容,避免缓冲区溢出。
  4. 内存优化:对不同长度的字符串使用不同大小的头部,减少内存开销。

三种编码(自动切换):

  • INT:存储整数值(如SET key 123),直接将数值存储在指针位置,无需额外分配。
  • EMBSTR:存储短字符串(≤44 字节)。Redis 对象头与 SDS 数据存储在同一块连续内存中,内存局部性好,一次分配完成。
  • RAW:存储长字符串(> 44 字节)。Redis 对象头与 SDS 数据分开分配

44 字节边界是根据 64 位系统内存对齐(jemalloc 分配器常用 64 字节块)精确计算得出的优化值。

二、List

List 的底层是QuickList,它是一个宏观上的双向链表,但每个链表节点 (quicklistNode) 内部并不直接存储数据,而是包含一个ListPack来紧凑存储多个元素。

QuickList 结构: [quicklistNode] <-> [quicklistNode] <-> [quicklistNode] ↓ ↓ ↓ ListPack ListPack ListPack [e1,e2,e3] [e4,e5,e6] [e7,e8,e9]

设计优势:

  • 对比纯链表:避免了每个元素都需要prev/next指针的巨大内存开销。
  • 对比纯 ListPack:避免了在超长连续内存中插入/删除元素时的大规模数据移动。

通过配置list-max-listpack-size可以控制每个 ListPack 的最大容量(如-2表示约 8KB),从而在内存紧凑性节点内操作性能之间取得平衡。

三、Set

Set 存储无序且唯一的元素,底层使用IntSetHashTable

  • IntSet:当所有元素都是整数元素数量 ≤set-max-intset-entries(默认 512)时使用。它是一个有序整数数组,支持二分查找(O(log N)),内存极其紧凑。
  • HashTable:当插入非整数元素元素数量超过阈值时,自动转换为 HashTable。此时只使用字典的键(Key)来存储元素,值(Value)统一为NULL,实现 O(1) 复杂度的查找。

关键点:

  • IntSet 升级:当新插入的整数超出当前编码范围(如从 int16 到 int32)时,会触发升级,重新分配内存并转换所有元素。升级是单向不可逆的。
  • HashTable 也使用渐进式 rehash,扩容机制与其他场景下的哈希表一致。

四、ZSet (Sorted Set)

ZSet 存储带分值(score)的有序唯一元素,底层使用ListPack字典(Dict) + 跳表(SkipList)的双结构。

  • ListPack:当元素数量 ≤zset-max-listpack-entries(默认 128)每个元素值长度 ≤zset-max-listpack-value(默认 64 字节)时使用。元素按分值连续紧凑存储。
  • Dict + SkipList:当不满足上述条件时使用。
    • 跳表 (SkipList):维护分值有序结构,支持 O(log N) 的范围查询(如ZRANGE,ZRANK)。
    • 字典 (Dict):实现 O(1) 复杂度的单点查询(如ZSCORE)。

双结构设计精髓:

  • 空间换时间:用额外空间(指针)同时获得 O(1) 查找和 O(log N) 范围查询。
  • 数据共享:两个结构中的元素值(SDS)指向同一内存对象,避免重复存储。

五、Hash

Hash 存储字段-值对(field-value),底层使用ListPackHashTable

  • ListPack:当字段数量 ≤hash-max-listpack-entries(默认 512)所有字段值长度 ≤hash-max-listpack-value(默认 64 字节)时使用。字段和值交替存储在 ListPack 中。
  • HashTable:当不满足上述条件时使用,提供 O(1) 的字段操作。

为什么小 Hash 还用 ListPack?

虽然 ListPack 的查询是 O(N),但对于小规模数据(几十个字段):

  1. 内存效率极高:比 HashTable 节省约 30%-50% 内存(无指针和额外元数据开销)。
  2. 缓存友好:数据连续存储,CPU 缓存命中率高。
  3. 自动转换:超过阈值后 Redis 会自动转为 HashTable,对应用透明。

这是一种典型的“二八定律”优化:为80%的小数据场景优化内存,20%的大数据场景则保证性能。

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

相关文章:

  • eslint-config-standard 高级用法:自定义规则与配置扩展技巧
  • 蓝桥杯备赛:Day8-小红杀怪
  • 从零开始:Snap 官方指南与实战技巧
  • Swup完全指南:如何为传统网站添加现代化单页应用体验
  • 2026四川仿竹护栏网梯队名录:核心参数与服务能力盘点 - 优质品牌商家
  • OpenClaw+Qwen3-14b_int4_awq:24/7自动化监控与告警系统
  • rot.js完全指南:如何利用现代JavaScript模块化开发Roguelike游戏
  • GLM-4-9B-Chat-1M一文详解:GLM-4-9B-Chat-1M与Qwen2.5-72B长文本对比
  • Dev-C++ 6.3搭配EasyX图形库:从安装到画圆的保姆级教程
  • OpenClaw对接Qwen3-4B-Thinking-2507-GPT-5-Codex-Distill-GGUF实战:3步完成本地模型调用
  • G-Helper终极指南:5分钟精通华硕笔记本性能调校
  • QWEN-AUDIO真实项目作品:某省级图书馆AI语音导读系统生成样本
  • 动态数组(类似vector)的简易实现
  • 2026年靠谱的集装箱厕所/集装箱岗亭用户口碑推荐厂家 - 行业平台推荐
  • 第三大的数
  • java架构一/1:微服务电商/地基/登录
  • OpenClaw浏览器控制:Qwen3.5-9B自动填写复杂Web表单
  • 2026年4月严苛环境靠谱氢气发电机厂家推荐:24小时发电机出租、UPS不间断电源租赁、临时发电机出租、乙醇发电机组选择指南 - 优质品牌商家
  • Tinycon终极指南:如何在网站favicon上优雅显示通知气泡的完整教程
  • Z-Image-Turbo_Sugar脸部Lora入门必看:从Xinference启动到Gradio出图完整流程
  • 蓝桥杯备赛:Day8-小苯的异或和
  • 2026年单玻隔断厂家排行:甘肃成品隔断、甘肃活动隔断、甘肃玻璃隔墙、甘肃玻璃隔断、甘肃百叶隔断、甘肃移动隔断选择指南 - 优质品牌商家
  • Qwen3.5-9B垂直场景:制造业BOM表解析+工艺图识别+故障推演
  • 二叉树(C语言)
  • 从零开始构建嵌入式安全:OP-TEE可信执行环境实战指南
  • Creo混合与扫描混合实战:从基础到高级建模技巧
  • 跨平台文件同步:OpenClaw调用Gemma-3-12b-it智能分类备份方案
  • IHaskell实战案例:利用梯度下降算法解决实际优化问题的完整演示
  • AI 设计模式 04:多智能体协作模式 —— 给 AI 组个团队,干活比你公司的人还利索
  • 光电对抗:激光与激光雷达成像探测制导及电子对抗(2)