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

Redis中常见数据结构底层实现结构是什么

Redis中常用数据结构的底层实现及原理如下:


一、String(字符串)

  • 底层实现:动态字符串(SDS)整数(int)。
    • SDS:当存储内容为文本或二进制数据时,使用SDS。其结构包含len(已用长度)、free(剩余空间)和buf(数据缓冲区),支持动态扩容和预分配内存。
    • int:当存储内容为64位整数时,直接存储数值以节省内存。
  • 特点:O(1)获取长度、二进制安全、减少内存重分配。

SDS(简单动态字符串)与C语言动态数组在实现原理、功能特性和适用场景上有显著区别,以下是具体对比:


1. 内存管理与扩容机制

  • SDS
    • 预分配策略:每次扩容时,若新长度小于1MB,分配与当前长度相等的空闲空间(len=free);若超过1MB,固定分配1MB空闲空间。
    • 惰性释放:缩短字符串时,不立即释放多余内存,而是记录在free字段中供后续复用,减少内存分配次数。
    • 自动扩容:API内部自动处理内存扩展(如sdscat会检查空间并扩容),无需用户干预。
  • C动态数组
    • 手动管理:需通过malloc/realloc手动分配和扩展内存,扩容失败需检查返回值(可能返回NULL)。
    • 无预分配每次扩容需重新分配内存,频繁操作易导致内存碎片或性能损耗。

2. 数据安全性与功能

  • SDS
    • 二进制安全:通过len字段记录长度,允许存储含\0二进制数据(如图片、音视频)。
    • 防溢出:API自动检查空间,避免拼接等操作导致的内存溢出。
  • C动态数组
    • 文本限制:依赖\0结尾,无法直接存储含\0的数据。
    • 缓冲区溢出风险:手动操作时若未正确计算长度,易覆盖相邻内存(如strcat未扩容导致溢出)。

3. 性能与复杂度

  • SDS
    • O(1)获取长度:通过len字段直接读取,无需遍历。
    • 高效操作:预分配和惰性释放减少内存分配次数,适合高频修改场景(如Redis键值操作)。
  • C动态数组
    • O(n)获取长度:需遍历数组或额外维护变量记录长度。
    • 手动优化需求:开发者需自行实现扩容策略(如指数增长)以平衡性能与内存使用。

4. 底层结构与兼容性

  • SDS
    • 结构体封装:包含lenfreeflags等元数据,支持多种编码(如emstrraw)优化内存布局。
    • 兼容C函数:底层buf仍以\0结尾,可复用部分C字符串函数(如strcmp)。
  • C动态数组
    • 简单指针+长度:仅通过指针和长度变量管理,无额外元数据支持。

总结

特性

SDS

C动态数组

长度获取

O(1)(通过len

字段)

O(n)(需遍历或额外记录)

安全性

防溢出、二进制安全

易溢出、仅支持文本

扩容策略

自动预分配+惰性释放

手动realloc

,无预分配

适用场景

高频修改、二进制数据存储

简单文本、固定或少量动态数据

SDS通过结构化设计和自动化内存管理,在性能与安全性上显著优于C动态数组,尤其适合Redis这类对内存和操作效率要求极高的场景


二、List(列表)

  • 底层实现:QuickList(Redis 3.2+)。
    • QuickList:由多个压缩列表(ziplist)通过双向链表连接而成,平衡内存与操作效率。
    • 压缩列表(ziplist):连续内存存储元素,适合小数据量(默认元素≤512且单元素≤64字节)。
  • 特点:支持双向头尾操作,O(1)时间复杂度插入/删除头部或尾部元素。

三、Hash(哈希)

  • 底层实现:ziplist或字典(dict)。
    • ziplist:当键值对数量≤512且键值长度≤64字节时,使用连续内存存储键值对。
    • dict:基于哈希表实现,通过拉链法解决冲突,支持动态扩容(负载因子>0.75时扩容)。
  • 特点:O(1)平均时间复杂度的插入、删除和查询。

四、Set(集合)

  • 底层实现:intset或字典(dict)。
    • intset:当所有元素为整数且数量≤512时,使用有序整数数组,支持二分查找。
    • dict:元素不满足条件时,转为哈希表实现。
  • 特点:元素唯一,O(1)平均时间复杂度的插入、删除和查询。

五、Sorted Set(有序集合)

  • 底层实现:ziplist或跳表(skiplist)+字典(dict)。
    • ziplist:当元素数量≤128且单元素≤64字节时,按分数和成员交替存储。
    • 跳表+字典:跳表维护有序性,字典实现成员到分数的映射,支持O(log N)范围查询和排名计算。
  • 特点:元素唯一且有序,范围查询效率高。

关键设计原理

  1. 动态转换:根据数据量或元素大小自动切换底层结构(如ziplist→dict或quicklist)。
  2. 内存优化:SDS预分配、ziplist紧凑存储、跳表共享索引减少内存占用。
  3. 性能平衡:跳表通过概率平衡实现高效查询,字典通过渐进式Rehash减少扩容阻塞。

通过灵活组合不同数据结构,Redis在内存效率与操作性能间取得平衡,适用于高并发场景。

http://www.dtcms.com/a/395762.html

相关文章:

  • 高频交易技术演进:从毫秒到纳秒的极限延迟优化之路
  • 从零开始搭建并部署一个基于Django和YOLO的智能模型项目
  • MySQL零基础学习Day2——数据库基础操作
  • 数学笔试选择题:题组1
  • Linux常用命令51——tail查看文件尾部内容
  • Django多数据库配置:mysql、mongo、redis、达梦
  • 图像拼接(反向拼接巨难,求指教!)
  • [免费]基于Python的深度学习音乐推荐系统(后端Django)【论文+源码+SQL脚本】
  • 南华 NHL-1 型加载减速工况法轻型柴油车烟度检测系统:技术解析与实战指南
  • 学习Java遇到的一些问题
  • 基于SpringBoot招聘信息管理系统
  • 多线程—线程通信之notifyAll()/wait()方法Demo
  • kotlin 常用函数
  • 2025年CSP-J1入门级初赛题解
  • vue3的基本指令以及对js的导入和导出
  • Linux 基础:关机与重启
  • React Native:分享Windows平台搭建react native并构建apk的操作流程和配置信息
  • EC24026露营灯警示灯芯片方案 报警声语音IC 单片机方案开发
  • 反量化的详细过程
  • C语言:实现3x3矩阵对角线求和
  • [Maven 基础课程]Maven 工程继承和聚合
  • 数据库--存储过程
  • mysql默认事务隔离级别下并发读不到最新数据解决方案
  • M3U8通用下载器
  • Vue动态组件详细用法指南
  • C#练习题——委托练习
  • 【TS4】简单的typescript练手项目
  • 前端学习手册-JavaScript函数与回调(十一)
  • Unity小游戏接入抖音敏感词检测
  • 【2025最新】01 Spring Boot 第一个小程序 for VS Code - 通过 Spring Initializr 网站创建