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

详解Redis数据结构(附源码)

引言

只有弄明白Redis数据结构,才能理解它如此快速的原因,并不只是它存储于内存,本篇文章将拆开Redis数据结构分析它高效的原因

字符串(String)


基本概念:字符串是 Redis 中最基本的数据结构,可以存储任何形式的字符串,包括文本、二进制数据等,一个字符串的最大长度可达 512MB。

底层代码:

struct sdshdr {
    // 记录 buf 数组中已使用字节的数量,等于 SDS 所保存字符串的长度
    int len;
    // 记录 buf 数组中未使用字节的数量
    int free;
    // 字节数组,用于保存字符串
    char buf[];
};
  • len:该字段记录了当前 SDS 中存储的字符串的实际长度。通过这个字段,获取字符串长度的操作时间复杂度为 O (1),而在传统 C 字符串中,需要遍历整个字符串来获取长度,时间复杂度为 O (n)。
  • free:它表示 buf 数组中尚未使用的字节数量。这个字段的存在使得 SDS 在进行字符串修改时,可以预先分配足够的空间,减少内存重新分配的次数。
  • buf:这是一个字符数组,用于实际存储字符串的内容。在数组的末尾,会以 '\0' 结尾,这样可以兼容部分 C 字符串函数。

总结以上:获取字符串长度时间复杂度O(1),减少内存分配次数,兼容C语言函数


应用场景
缓存数据:可缓存网页内容、数据库查询结果等,将网页的 HTML 内容以字符串形式存储,键为网页的 URL。
计数器:用于统计网站访问量、用户点赞数等,通过incr命令记录文章阅读次数。

列表(List)

基本概念
列表是 Redis 中的一种线性数据结构,支持在头部或尾部插入和删除元素。列表可以存储多个字符串元素,元素可以重复,最大长度为 2^32 - 1。

底层代码
Redis 列表的底层实现有两种:

  1. 压缩列表(ziplist):用于存储小列表,节省内存。

  2. 双向链表(linkedlist):用于存储大列表,支持快速的头尾操作。

    // 压缩列表结构(ziplist)
    struct ziplist {
        unsigned char *zlbytes;  // 整个压缩列表占用的字节数
        unsigned char *zltail;   // 最后一个节点的偏移量
        unsigned char *zllen;    // 节点数量
        unsigned char *zlentry;  // 节点数据
    };
    
    // 双向链表节点结构
    struct listNode {
        struct listNode *prev;  // 前驱节点
        struct listNode *next;  // 后继节点
        void *value;            // 节点值
    };
    
    // 双向链表结构
    struct list {
        listNode *head;         // 链表头节点
        listNode *tail;         // 链表尾节点
        unsigned long len;      // 链表长度
    };

    特点:存储偏移量避免遍历查找末尾字节

    压缩列表:内存紧凑,适合小列表,但插入和删除效率较低。

    双向链表:支持 O(1) 时间复杂度的头尾插入和删除操作,适合频繁修改的场景。

    应用场景:根据不同指定产生中间件

    消息队列:使用 LPUSH 和 RPOP 实现队列。

    最新消息列表:使用 LPUSH 和 LRANGE 获取最新消息。

    栈:使用 LPUSH 和 LPOP 实现栈。

哈希(Hash)

基本概念
哈希是 Redis 中的一种键值对集合,适合存储对象。每个哈希可以存储多个字段和值,字段和值都是字符串类型。

底层代码
Redis 哈希的底层实现有两种:

  1. 压缩列表(ziplist):用于存储小哈希,节省内存。

  2. 字典(dict):用于存储大哈希,基于哈希表实现。

    // 字典结构
    struct dict {
        dictEntry **table;       // 哈希表数组
        unsigned long size;      // 哈希表大小
        unsigned long sizemask;  // 哈希表大小掩码
        unsigned long used;      // 已使用的节点数
    };
    
    // 哈希表节点结构
    struct dictEntry {
        void *key;               // 键
        union {
            void *val;
            uint64_t u64;
            int64_t s64;
        } v;                     // 值
        struct dictEntry *next;  // 指向下一个节点(解决哈希冲突)
    };
  • 压缩列表:内存紧凑,适合小哈希。

  • sizemask(哈西表大小掩码): 是哈希表大小减 1(size - 1),用于将哈希值映射到哈希表的索引范围内。它的主要作用是:

              快速计算索引:通过 hash & sizemask 的方式,将哈希值映射到哈希表的索引位置。

              保证索引在合法范围内:由于 sizemask = size - 1,且 size 是 2 的幂次方,hash &                  sizemask 的结果一定在 [0, size-1] 范围内。

  • 字典:支持 O(1) 时间复杂度的查找、插入和删除操作。

  应用场景:

  • 存储对象:如用户信息、商品信息。

  • 字段级操作:可以直接修改某个字段,而不需要读取整个对象。

集合(Set)

基本概念
集合是 Redis 中的一种无序且唯一的数据结构,适合存储不重复的元素。

底层代码
Redis 集合的底层实现有两种:

  1. 整数集合(intset):用于存储整数集合,节省内存。

  2. 字典(dict):用于存储大集合,基于哈希表实现。

    // 整数集合结构
    struct intset {
        uint32_t encoding;  // 编码方式(int16、int32、int64)
        uint32_t length;    // 集合长度
        int8_t contents[];  // 集合内容
    };
    
    // 字典结构(同上)
  • 整数集合:内存紧凑,适合存储整数。

  • 字典:支持 O(1) 时间复杂度的查找、插入和删除操作。

应用场景

  • 去重:如存储用户 ID、标签。

  • 集合运算:如交集、并集、差集。

位图(Bitmap)

基本概念
位图是 Redis 中的一种基于字符串的数据结构,每个 bit 位表示一个状态。不同于布尔数组,它的每个位只占一个bit

底层代码
位图底层使用字符串(SDS)存储。

// SDS 结构(同字符串)
struct sdshdr {
    int len;    // 字符串长度
    int free;   // 未使用字节数
    char buf[]; // 字节数组
};
  • 极省内存:每个 bit 位存储一个状态。

  • 位操作:支持高效的位运算(如 AND、OR、NOT)。

应用场景

  • 用户签到:记录用户每天的签到状态。

  • 活跃用户统计:统计某段时间内的活跃用户。

位图的高效性

  1. 内存效率

  • 每个位只占用 1 bit,比使用布尔数组或整数数组更节省内存。
  • 例如,存储 100 万个布尔值只需要 125KB 内

    2. 位运算性能

  • Redis 的位操作是基于 CPU 的位运算指令实现的,性能非常高。
  • 例如,BITCOUNT 命令使用高效的算法统计 1 的数量。

   3. 批量操作

  • 支持批量设置和获取位值,减少网络开销。

    相关文章:

  1. Visonpro 检测是否有缺齿
  2. 【Flink快速入门-5.流处理之多流转换算子】
  3. STM32的DMA解释
  4. Go语言精进之路读书笔记(第二部分-项目结构、代码风格与标识符命名)
  5. 案例-05.部门管理-新增
  6. 数据大屏炫酷UI组件库:B端科技风格PSD资源集
  7. RISC-V平台编译 state-thread x264 ffmpeg zlog
  8. 分布式光纤传感:为生活编织“感知密网”
  9. Node.js 中的 Event 模块详解
  10. 【JavaEE进阶】Spring Boot日志
  11. java断点调试(debug)
  12. 人工智障的软件开发-自动流水线CI/CD篇-docker+jenkins部署之道
  13. Spring Boot应用开发
  14. C++:构造函数和析构函数
  15. 机器学习--实现多元线性回归
  16. 【重构谷粒商城】06:Maven快速入门教程
  17. 【BUUCTF】[网鼎杯 2018]Comment
  18. 通俗诠释 DeepSeek-V3 模型的 “671B” ,“37B”与 “128K”,用生活比喻帮你理解模型的秘密!
  19. 【股票数据API接口25】如何获取最近10天历史成交分布数据之Python、Java等多种主流语言实例代码演示通过股票数据接口获取数据
  20. 自己部署 DeepSeek 助力 Vue 开发:打造丝滑的折叠面板(Accordion)
  21. 金科股份:去年营收约275亿元,今年确保所有项目“零烂尾”
  22. 杨国荣︱学术上的立此存照——《故旧往事,欲说还休》读后
  23. 王毅会见泰国外长玛里:坚决有力打击电诈等跨境犯罪
  24. 国务院任免国家工作人员:饶权任国家文物局局长
  25. 传智教育连续3个交易日跌停:去年净利润由盈转亏
  26. 加拿大驾车撞人事件遇难人数升到11人