`
OrangeHolic
  • 浏览: 260732 次
  • 来自: 北京
社区版块
存档分类
最新评论

Redis内部涉及 的数据结构

 
阅读更多
Redis就是内存中维持一个巨大的字典,字典的key节点及value节点是一个个数据结构。

在这里简单介绍一下Redis用到的数据结构。

1.简易动态字符串(sds)

Redis没有使用传统的C字符串形式,取而代之的是自己实现了一个简单动态字符串简易动态字符串结构,简称为SDS(Simple Dynamic Strings)。

SDS兼容C字符串的同时,带来了二进制安全、计算更有效率、杜绝缓冲区溢出等优点。

struct sdshdr {
    /*字符串的长度。因为最后一个字节需为'\0',所以也是buf已经使用的空间的长度-1*/
    int len;
    /*buf中剩余可用空间的长度*/
    int free;
    /*数据空间*/
    char buf[];
};


"hello"的存储方式在内部就可能(小伙伴们考虑一下为啥是可能呢?)表示成下面的形式



2.双链表(adlist)
双链表是一个基本的数据结构,样子就像一串回形针。
Redis中的双链表跟小伙伴们在《数据结构》中学到的双链表一模一样,在此就不详细介绍了。
放个示意图



3.字典(dict)
作为key-value数据库,上面提到过整个Redis就是一个巨大的字典,字典的设计决定了此类产品的成败。

Redis的字典由字典类型特定函数和2个哈希表表组成。特定函数包括计算哈希值、复制键\值等一些列函数组成,两个哈希表用来实现渐进式 rehash。

typedef struct dict {
    /*类型特定函数组成的结构体*/
    dictType *type;
    /*私有数据*/
    void *privdata;
    /*两个哈希表*/
    dictht ht[2];
    /*是否在进行rehash中*/
    int rehashidx;
    /*目前正在运行迭代器的数量*/
    int iterators;
} dict;


哈希表hash算法采用比较流行的MurmurHash2算法,对于规律性较强的key,节点更加“分布均匀”。

用链表法处理hash碰撞,将多个哈希值相同的节点串连在一起。

渐进式 rehash是Redis字典特性,防止一次rehash导致系统资源使用增高可能导致的卡死。

非rehash时,数据会放到哈希表ht[0];rehash时,新插入的数据会放置到ht[1],同时每次字典操作都会从ht[0]移动一定数量的哈希表节点到ht[1],直到ht[0]节点数变为0,
然后执行ht[0]=ht[1],重置ht[1]。

示意图为正在rehash的字典的示意



4.跳表(skiplist)
跳表是种偷懒的设计,用来替代平衡树,跳表的算法有同平衡树一样的渐进的预期时间边界,并且更简单、更快速和使用更少的空间。
跳表是按照层级来建造的,每层皆是一个链表,上层是下层的快速跑道可以更快的定位数据所在的位置范围,查询数据时逐层定位缩小范围直至范围变为1或者0。

typedef struct zskiplistNode {
    /* 成员对象,即存储的数据*/
    robj *obj;
    /*分值,用来排序*/
    double score;
    /*后退指针,用于跳表的从尾到头的遍历*/
    struct zskiplistNode *backward;
    /*层级*/
    struct zskiplistLevel {
        /*前进指针,指向本层的下一个节点*/
        struct zskiplistNode *forward;
        /* 跨度,记录到本层下一个节点的距离*/
        unsigned int span;
    } level[];
} zskiplistNode;


各个level节点记录前进指针的同时也会记录到下一个节点的跨度,遍历跳表只需按照跨度等于1从头到尾访问节点即可。



5.压缩列表(ziplist)

压缩列表是Redis为解决内存而设计的存储方式,到满足一定的条件(如元素的个数少、key或者value的长度短)的情形下,List和字典都有可能使用压缩列表存储。

压缩列表的存储结构如下:





zlbytes 记录整个压缩表占用的字节数
zltail 记录压缩列表尾节点距离压力表第一个字节地址的偏移
zllen 表示压缩节点的个数
zlentry 为压缩表节点
zlend 压缩表结尾特殊字节,为0xFF

zlentry的结构如下

typedef struct zlentry {
    /*prevrawlen :前置节点的长度 ,prevrawlensize :编码 prevrawlen 所需的字节大小*/
    unsigned int prevrawlensize, prevrawlen;

    /*len :当前节点值的长度,lensize :编码 len 所需的字节大小*/
    unsigned int lensize, len;
    /*当前节点 header 的大小,等于 prevrawlensize + lensize*/
    unsigned int headersize;
    /*当前节点存储何种类型的数据*/
    unsigned char encoding;
    /*数据指针*/
    unsigned char *p;

} zlentry;



6.整数集合(intset)

当集合中只有整数时,Redis会使用下面的结构来存储这些整数。

typedef struct intset {
    /*编码方式*/
    uint32_t encoding;
    /*包含的元素个数*/
    uint32_t length;
    /*集合中的元素,会根据编码方式来决定一个元素占用多少个字节*/
    int8_t contents[];
} intset;





  • 大小: 8.6 KB
  • 大小: 39.3 KB
  • 大小: 92 KB
  • 大小: 65 KB
  • 大小: 13.3 KB
  • 大小: 16.2 KB
分享到:
评论

相关推荐

    redis_3.2.9_内存分布分析

    通过上述分析,可以看出Redis内部对内存的使用十分高效,通过灵活运用不同的数据结构以及精细的内存管理策略,实现了高性能和稳定性。同时,Redis的源码分析对于理解这些知识有着不可替代的作用,能够帮助开发者深入...

    redis cookbook

    而且,作者还讨论了如何使用Lua脚本在Redis内部执行自定义命令,以及如何利用Redis的发布订阅功能实现消息的发布和订阅机制。 《Redis Cookbook》的印刷历史显示,这本书是在2011年8月首次出版的,尽管时间已久,...

    redis操作源代码以及查看redis的情况的辅助代码以及redis安装包

    2. **数据结构**:Redis内部使用高效的数据结构,如哈希表、链表、跳跃表和压缩树等,源代码可以帮助理解这些数据结构的实现细节。 3. **事务处理**:Redis支持单个命令或多个命令的原子性执行,源代码中可能包括...

    redis虚拟机环境搭建与安装redis

    在实际应用中,你还可以进一步学习Redis的数据结构、持久化机制、主从复制、哨兵系统以及集群配置等相关知识,以充分利用其功能。对于源码探索,可以访问Redis的GitHub仓库,了解其内部实现,这对深入理解Redis的...

    Redis 设计与实现

    标题中的“设计与实现”暗示了该书将深入到Redis内部,探讨其核心算法和数据结构,以及如何将这些设计思想转化为实际可运行的代码。这对于想深入了解Redis工作原理的开发者或数据库管理员来说,是一本宝贵的参考资料...

    redis深度历险,redis佳作。

    在深入学习部分,作者会剖析Redis的内部工作原理,包括数据结构实现、命令执行流程、网络模型等,这对于优化Redis的使用和性能调优至关重要。读者可以通过这部分内容理解Redis为何能实现毫秒级的响应时间,并学习...

    redis-3.2.11.tar.gz 以及redis-3.3.5.gem

    它的高效性得益于其内存存储特性,以及丰富的数据结构支持,如字符串、哈希、列表、集合和有序集合。Redis-3.2.11.tar.gz 文件是Redis 3.2.11版本的源代码包,通过这个文件,我们可以了解Redis的内部实现并进行...

    redis-3.2.1.rar

    Redis是一个开源的、基于内存的数据结构存储系统,它可以作为数据库、缓存和消息代理。它的数据结构包括字符串、哈希、列表、集合、有序集合等,支持丰富的操作命令,使得在处理各种数据需求时非常灵活。 Redis-...

    spring4.0结合redis3.0

    此外,Redis 3.0引入了一些新特性,比如Lua脚本支持、流(Streams)数据结构、Geo索引、HyperLogLog等。这些特性可以通过Spring Data Redis的API来利用,增强应用的功能和性能。 总的来说,Spring 4.0与Redis 3.0的...

    Redis学习笔记

    "深入redis学习(八)--redis zipmap.doc"介绍了一种内部使用的紧凑数据结构,用于节省内存。Zipmap在存储少量键值对时很有优势,但随着数据增长,Redis会自动转换为普通哈希表以保证性能。 "深入redis学习(九)--...

    最新版 redis-6.0.5.tar.gz

    Redis 是一个高性能的键值数据库,它以内存存储为主,数据持久化为辅,支持多种数据结构如字符串、哈希、列表、集合、有序集合等。`redis-6.0.5.tar.gz` 是 Redis 官方发布的 6.0.5 版本的源代码压缩包,该版本可能...

    redis7.0的tar.gz压缩包

    3. **流数据增强**:Stream数据结构在7.0中得到了扩展,支持更丰富的查询和分析能力,如更灵活的GROUP BY和窗口函数,这使得Redis更适合实时数据分析场景。 4. **安全性提升**:Redis 7.0增强了安全特性,包括内置...

    redis源码,

    `dict.c`和`dict.h`实现了字典数据结构,这是Redis中键值对存储的基础。字典使用哈希表作为底层实现,支持动态调整大小以适应数据量的变化。`server.c`中的`server.db`数组则包含了所有数据库,每个数据库都是一个...

    redis-unstable.zip_Redis C_c redis_redis_redis c++_visual c

    1. **Redis基础知识**:Redis是一个内存数据结构存储系统,支持多种数据类型,如字符串、哈希、列表、集合、有序集合。它通过提供丰富的命令操作这些数据类型,具有高并发性、低延迟的特点。Redis的数据持久化主要...

    redis文档

    标签“源码”意味着可能涉及 Redis 的源代码分析,这对于开发者来说是宝贵的资源,能够帮助他们理解 Redis 的内部实现机制,比如数据结构优化、网络事件处理模型(例如使用epoll或kqueue)、命令处理流程等。...

    Redis基本原理、优化和应用示例.pdf

    而对于Zipmap,这是一种用于存储小型键值对的内部数据结构,当键值对增多或大小超过一定阈值时,会自动转换为哈希表。 2. Redis优化 - **内存优化**:Redis的内存管理很重要,可以通过设置最大内存限制、使用LRU...

    Redis-x64-3.zip

    7. **性能提升**:通过对内部数据结构的调整和算法优化,3.x在处理大量请求时性能得到显著提升。 解压"Redis-x64-3.zip"后,你将可能找到以下内容: - `redis-server.exe`:Redis服务器的可执行文件。 - `redis-cli...

    redis学习文档

    此外,《redis设计与实现》则可能深入到Redis的实现细节,包括Redis的数据结构优化、内存管理策略、网络模型(基于事件的epoll模型)以及多线程模型等。这本书可能会详细解析Redis的主从复制、Sentinel哨兵系统和...

    Redis Essentials

    Redis是一种开源的高性能键值存储系统,它支持多种类型的数据结构,如字符串、列表、集合、有序集合、位图、超日志和地理空间索引。Redis以内存存储和持久化的方式,提供快速的读写速度,通常被用作数据库、缓存和...

    Ecology&Emessage&Emobile集群+redis部署方案.zip

    因为Redis操作速度快,支持多种数据结构(如字符串、哈希、列表、集合和有序集合),适合存储热数据,减少对数据库的直接访问,从而减轻数据库压力,提高系统整体性能。 集群部署Redis可以进一步增强其可靠性。通过...

Global site tag (gtag.js) - Google Analytics