iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >redis笔记-数据结构篇
  • 393
分享到

redis笔记-数据结构篇

2024-04-02 19:04:59 393人浏览 安东尼
摘要

2018-1-3 by Atlas 1. SDS 描述 Redis底层是C语言编写,而redis没有直接使用C语言的字符串表示,是自己构建了一种名为简单动态字符串的抽象类型,即SDS(simple

2018-1-3 by Atlas

1. SDS

  • 描述

Redis底层是C语言编写,而redis没有直接使用C语言的字符串表示,是自己构建了一种名为简单动态字符串的抽象类型,即SDS(simple dynamic string)。
redis数据库里,包含字符串值的键值对在底层都是SDS实现的,可以说SDS是基石。
AOF模块中的AOF缓冲区,以及客户端状态中的输入缓冲区,都是SDS实现的。

  • 定义
struct sdshdr {
        // 记录buf数组中已使用字节的数量
        // 等于SDS所保存字符串的长度
        int len;
        // 记录buf数组中未使用字节的数量
        int free;
        // 字节数组,用于保存字符串
        char buf[];
}
  • 结构

redis笔记-数据结构篇

  • free属性值为0,表示这个SDS没有未使用空间。
  • len属性值为5,表示这个SDS保存了一个5字节长的字符串。
  • buf属性是char类型数组,数组前5个字节分别保存'R'、'e'、'd'、'i'、's'5个字符,最后1个字节保存了空字符'\0'。
  • buf长度=len+free+1。
  • 策略
  • SDS遵循C字符串以空字符'\0'结尾的惯例好处是可以直接重用一部分C字符串函数。
  • 较C字符串SDS在len属性中记录了SDS本身的长度,从而获取SDS长度复杂度仅为O(1)。
  • 较C字符串SDS读取字符不是通过结尾空字符'\0'而是len属性因此更安全,使得redis不仅可以保存文本数据,还可以保存任意格式的二进制数据。
  • 较C字符串SDS的空间分配策略完全杜绝了发生缓冲区溢出的可能,检查free属性是否满足修改需求,如果不满足,自动拓展空间然后再执行修改操作,如果空间足够,则无需执行内存重分配。
  • 空间分配策略优化策略空间预分配和惰性空间释放减少了内存重分配次数。
  • 空间预分配公式:
    如果修改SDS后,SDS的len将小于1MB,那么分配和len属性同样大小的free空间;
    如果修改SDS后,SDS的len将大于等于1MB,那么分配1MB的free空间。
  • 惰性空间释放策略即SDS空间修改操作释放多出来的空间保留,避免缩短字符串的内存重分配和提供将来有可能的字符串增长。
  • SDS提供了释放SDS空间的api,所以不必担心惰性空间释放会造成内存浪费。

2. LIST

  • 描述

链表提供了高效的节点重排能力,以及顺序性的节点访问方式,并且可以通过增删节点来灵活地调整链表的长度。
列表键的底层实现之一就是链表。
发布与订阅、慢查询、监视器等功能也用到了链表,redis服务器本身还使用链表来保存多个客户端的状态信息,以及使用链表来构建客户端输出缓冲区。

  • 定义
typeof struct listnode {
        // 前置节点
        struct listNode *prev;
        // 后置节点
        struct listNode *next;
        // 节点的值
        void *value;
} listNode;
typeof struct list {
        // 表头节点
        listNode *head;
        // 表尾节点
        listNode *tail;
        // 链表包含的节点数量
        unsigned long len;
        // 节点值复制函数
        void *(*dup)(void *ptr);
        // 节点值释放函数
        void (*free)(void *ptr);
        // 节点值对比函数
        int (*match)(void *ptr,void *key);
} list;
  • 结构

redis笔记-数据结构篇

  • 策略

双端:链表节点带有prev和next指针,获取某个节点的前置节点和后置节点的复杂度都是O(1)。
无环:表头节点的prev指针和表尾节点的next指针都指向NULL,对链表的访问以NULL为终点。
带链表长度计数器:list结构的len属性使得获取链表节点数量的复杂度是O(1)。
多态:链表节点使用void *指针来保存节点值,并且可以通过list结构的dup、free、match属性为节点设置类型特定函数,所以链表可以保存各种不同类型的值。

3. HASH

  • 描述

字典是一种用于保存键值对的抽象数据结构
字典中的键都是独一无二的。
redis数据库就是使用字典来作为底层实现的。
字典还是哈希键的底层实现之一。

  • 定义
typeof struct dictEntry {
        // 键
        void *key;
        // 值
        uNIOn{
                void *val;
                unit64_t u64;
                int64_t s64;
        } v;
        // 下个节点
        struct dictEntry *next;
} dictEntry;
typeof struct dictht {
        // 哈希表数组
        dictEntry **table;
        // 哈希表大小
        unsigned long size;
        // 哈希表大小掩码,用于计算索引值
        // 总是等于size-1
        unsigned long sizemask;
        // 哈希表已有节点的数量
        unsigned long used;
} dictht;
typeof struct dictType {
        // 计算哈希值的函数
        unsigned int (*hashFunction)(const void *key);
        // 复制键的函数
        void *(*keyDup)(void *privdata, const void *key);
        // 复制值的函数
        void *(*valDup)(void *privdata, const void *obj);
        // 对比键的函数
        int (*keyCompare)(void *privdata, const void *key1,const void *key2);
        // 销毁键的函数
        void (*keyDestructor)(void *privdata, void *key);
        // 销毁值的函数
        void (*valDestructor)(void *privdata, void *val);
} dictType;
typeof struct dict {
        // 类型特定函数
        dictType *type;
        // 私有数据
        void *privadata;
        // 哈希表
        dictht ht[2];
        // rehash索引
        // 当不在进行rehash时,值为-1
        int trehashidx;
} dict;
  • 结构

redis笔记-数据结构篇

  • 策略
  • ht属性是包含两个项的数组,一般情况下,字典只是用ht[0],ht[1]只有rehash时使用。
  • 哈希算法
    hash = dict->type->hashFuncton(key);
    index = hash&dict->ht[x].sizemash;
  • hash冲突的解决途径是链接地址法。
  • 与java数据结构HashMap不同,是单链表,相同是,插入表头位置,新插入的节点更偏向接下来被访问。
  • rehash操作:
    如果执行拓展操作,那么ht[1]的大小为第一个大于等于ht[0].used*2的2的n次方幂;
    如果执行收缩操作,那么ht[1]的大小为第一个大于等于ht[0].used的2的n次方幂。
  • 哈希表负载因子公式:
    负载因子 = 哈希表已保存节点数量 / 哈希表大小
    load_factor = ht[0].used / ht[0].size
  • 程序自动执行哈希表拓展操作的条件:
    服务器目前没有在执行BGSAVE或BGREWRITEAOF命令,并且负载因子大于等于1。
    服务器目前正在执行BGSAVE或BGREWRITEAOF命令,并且负载因子大于等于5。
  • 程序自动执行哈希表收缩操作的条件:
    哈希表的负载因子小于0.1。
  • 哈希表分而治之渐进式rehash步骤:
    1)为ht[1]分配空间,字典同时持有ht[0]和ht[1]。
    2)rehashidx设置为0,表示rehash开始。
    3)rehash进行期间,每次对字典执行删除、查找或者更新操作时,会在两个哈希表上进行,程序除了执行指定的操作外,还会顺带将ht[0]的键值对rehash到ht[1],每次对字典执行添加操作时,新添加的键值对一律保存到ht[1]而不在对ht[0]添加,当rehash后,将rehashidx值增一。
    4)随着字典操作的不断进行,最终某个时间点,ht[0]的所有键值对都会rehash到ht[1],将rehashidx设为-1,表示rehash操作完成。
    5)释放ht[0],并将ht[1]设置为ht[0],然后为ht[1]分配一个空白哈希表。

4. SKIPLIST

  • 描述

跳跃表是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。
跳跃表支持平均O(logN)、最坏O(N)复杂度的节点查找,还可以通过顺序性来批量处理节点。
大部分情况下,跳跃表的效率和平衡树相媲美,并且实现较为简单。
redis使用跳跃表一个地方是作为有序集合键的底层实现之一,另一个地方是在集群节点中用作内部数据结构。

  • 定义
typeof struct zskiplistNode {
        // 后退指针
        struct zskiplistNode *backward;
        // 分值
        double score;
        // 成员对象
        robj *obj;
        // 层
        struct zskiplistLevel {
                // 前进指针
                struct zskiplistNode *forward;
                // 跨度
                unsigned int span;
        } level[];
} zskiplistNode;
typeof struct zskiplist {
        // 表头节点,表尾节点
        struct skiplistNode *header,*tail;
        // 表中节点数量
        unsigned long length;
        // 表中最大层数
        int level;
} zskiplist;
  • 结构

redis笔记-数据结构篇

redis笔记-数据结构篇

  • 策略

header指向跳跃表的表头节点。
tail指向跳跃表的表尾节点。
level记录跳跃表内表头外层数最大的节点的层数。
length记录跳跃表内表头外节点的数量。
层:前进指针用于访问位于表尾方向的节点,而跨度则记录前进指针指向节点和当前节点的距离。
后退指针指向位于当前节点的前一个节点,从表尾向表头遍历时使用。
各个节点按各自所保存的分值从小到大排列。

5. INTSET

  • 描述

整数集合是集合键的底层实现之一,当一个集合只包含整数值元素,并且这个集合的元素数量不多时,redis就会使用整数集合作为集合键的底层实现。
可以保存整数值类型有int16_t、int32_t、int64_t。

  • 定义
typeof struct intset {
        // 编码方式
        unit32_t encoding;
        // 集合包含的元素数量
        unit32_t lenght;
        // 保存元素的数组
        int8_t contents[];
} intset;
  • 结构

redis笔记-数据结构篇

INTSET_ENC_INT16表示整数集合的底层实现是int16_t类型的数组,集合保存的都是int16_t类型的整数值。
length属性值为5表示包含五个元素。
contents数组按从小到大属性保存集合的五个元素。
contents数组的大小等于16 * 5 = 80 位。

redis笔记-数据结构篇

INTSET_ENC_INT64表示整数集合的底层实现是int64_t类型的数组,集合保存的都是int64_t类型的整数值。
length属性值为4表示包含四个元素。
contents数组按从小到大属性保存集合的四个元素。
contents数组的大小等于64 * 4 = 256 位。

  • 策略

升级整数集合并添加新元素分三步:
1)根据新元素类型拓展整数集合底层数组的空间并为新元素分配空间。
2)将底层数组现有的所以元素都转换成与新元素相同的类型,并将类型转换后的元素放到正确的位上,需要维持底层数组的有序性质不变。
3)将新元素添加到底层数组。

6. ZIPLIST

  • 描述

压缩列表是列表键和哈希键的底层实现之一。
当一个列表键只包含少量列表项,并且每个列表项要么是小整数值,要么是短字符串,那么redis会使用压缩列表来作为列表键的底层实现。
当一个哈希键只包含少量键值对,并且每个键值对要么是小整数值,要么是短字符串,那么redis会使用压缩列表来作为哈希键的底层实现。

  • 定义

一系列特殊编码的连续内存块组成的顺序型数据结构。可以包含任意多个节点,每个节点可以保存一个字节数组或者一个整数值。

  • 结构

redis笔记-数据结构篇

zlbytes记录整个压缩列表占用的内存字节数。
zltail记录压缩列表表尾节点距离压缩列表的起始地址有多少字节,通过整个偏移量,程序无须遍历整个压缩列表就可以确定表尾节点的地址。
zllen记录压缩列表的节点数量。
entryX是压缩列表的节点。
zlend用于标记压缩列表的末端。

  • 策略

压缩列表从表尾节点倒叙遍历,首先指针通过zltail偏移量指向表尾节点,然后通过指向节点记录的前一个节点的长度依次向前遍历访问整个压缩列表。

以上就是redis基本数据类型的底层数据结构。

参考文献:《redis设计与实现》

您可能感兴趣的文档:

--结束END--

本文标题: redis笔记-数据结构篇

本文链接: https://www.lsjlt.com/news/38120.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 来年加薪必备,2020年攻破数据结构与算法学习笔记-数据结构篇
    著名数据专家沃斯曾说:算法+数据结构=程序今天我们就来讲讲数据结构1. 数组数组(Array)是一种线性表数据结构。它用一组连续的内存空间,来存储一组具有相同类型的数据。具有的特性:线性表连续的内存空间相同类型的数据可以随机访问数据操作比较...
    99+
    2023-06-04
  • python 数据结构篇
    在众多编程语言里,数据结构与算法都可以说是至关重要的基础。但是对于python而言,因为其本身就是用C实现的,其速度和效率本身较低,因而pyhon没有像其他语言那样那么重视数据结构与算法(python最引以为傲的应该是其功能强大而丰富的各种...
    99+
    2023-09-13
    python 开发语言 数据结构
  • PHP学习笔记:数据结构与算法
    概述:数据结构和算法是计算机科学中非常重要的两个概念,它们是解决问题和优化代码性能的关键。在PHP编程中,我们常常需要使用各种数据结构来存储和操作数据,同时也需要使用算法来实现各种功能。本文将介绍一些常用的数据结构和算法,并提供相应的PHP...
    99+
    2023-10-21
    学习笔记 PHP 数据结构 PHP 算法
  • python学习笔记(三)—数据库篇
    一、数据库编程 数据库编程是指在应用程序中使用数据库管理系统(DBMS)进行数据存储、检索和处理的过程。数据库提供了一种结构化的方式来组织和存储数据,使得数据的管理更加高效和可靠。 1.1 关系数据库...
    99+
    2023-09-18
    python 学习 笔记
  • 结构化数据和非结构化数据的提取【Python篇】
    结构化数据和非结构化数据的提取【Python篇】 总结一下Pyhon提供的可以提取结构化数据以及非结构化数据的主流库。 1.常见数据的分类: 依据响应分类(附带对应的常用的解析方法~): 结构化...
    99+
    2023-09-06
    python 数据的提取 json和jsonpath模块 re和xpath模块 bs4和pyquery库
  • redis怎么看数据结构
    在 Redis 中,可以使用 `TYPE` 命令来查看键对应的数据结构类型。具体语法如下:```TYPE key```其中,`key...
    99+
    2023-08-24
    redis
  • Java数据结构之顺序表篇
    目录一.线性表 二.顺序表1.概念及结构2.顺序表的实现打印顺序表获取顺序表的有效长度在pos位置新增元素判断是否包含某个元素查找某个元素对应的位置获取/查找pos位置的元...
    99+
    2024-04-02
  • Java数据结构之复杂度篇
    目录一.算法效率二. 时间复杂度1.时间复杂度的概念2.大O的渐进表示方法3.实例分析与计算三.空间复杂度1.空间复杂度的概念2.实例分析与计算 四.写在最后一.算法效率 ...
    99+
    2024-04-02
  • Redis中数据结构是什么
    这篇文章主要介绍了Redis中数据结构是什么,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。在实际开发,Redis使用会频繁,那么在使用过程中...
    99+
    2024-04-02
  • redis中有哪些数据结构
    小编给大家分享一下redis中有哪些数据结构,希望大家阅读完这篇文章后大所收获,下面让我们一起去探讨吧!redis数据结构有哪些?字符串(strings):存储整数(比如计数器)和字符串(废话。。),有些公...
    99+
    2024-04-02
  • Redis数据结构是怎样的
    这篇文章主要介绍“Redis数据结构是怎样的”,在日常操作中,相信很多人在Redis数据结构是怎样的问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Redis数据结构是怎样的”的疑惑有所帮助!接下来,请跟着小编...
    99+
    2023-06-27
  • Redis支持哪些数据结构
    字符串(Strings) 哈希表(Hashes) 列表(Lists) 集合(Sets) 有序集合(Sorted Sets) 位图(...
    99+
    2024-04-09
    Redis
  • Redis底层数据结构详解
    Redis作为Key-Value存储系统,数据结构如下: Redis没有表的概念,Redis实例所对应的db以编号区分,db本身就是key的命名空间。 比如:user:1000作为...
    99+
    2024-04-02
  • Redis的六种底层数据结构(小结)
    目录1、简单动态字符串(SDS)2、链表3、字典哈希表哈希表节点字典4、跳跃表跳跃表节点(zskiplistNode)跳跃表(zskiplist)5、整数集合6、压缩列表1、简单动态...
    99+
    2024-04-02
  • redis中数据结构有哪几种
    小编给大家分享一下redis中数据结构有哪几种,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!redis数据库中有五种数据结构,它们分别是:string-字符串、Hash-字典、List-列...
    99+
    2024-04-02
  • redis中hash数据结构及说明
    目录hash的数据结构ziplist底层实现字典底层实现扩容缩容总结hash的数据结构 hash底层数据结构的实现包括两种:ziplist和字典当保存的所有键值对字符串长度小于 64 字节并且键值对数量小于 512 时使...
    99+
    2023-01-28
    redis hash数据结构 redis hash hash数据结构
  • Redis的数据结构有哪几种
    Redis的数据结构主要分为以下几种: 字符串(string):最基本的数据结构,可以存储文本、数字等类型的数据。 列表(list...
    99+
    2024-03-01
    Redis
  • Redis的数据结构都有哪些
    Redis的数据结构主要有以下几种:1. 字符串(string):存储字符串类型的值,可以是普通字符串、整数或浮点数。2. 列表(l...
    99+
    2023-08-23
    Redis
  • redis数据结构有哪些内容
    本篇内容主要讲解“redis数据结构有哪些内容”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“redis数据结构有哪些内容”吧!redis不只是一个简单的键(ke...
    99+
    2024-04-02
  • redis缓存用什么数据结构
    redis 缓存支持多种数据结构,包括:字符串、哈希表、列表、集合、有序集合、地理空间数据类型、hyperloglog 和位图。每种数据结构都针对特定应用场景进行了优化,从而提高了 re...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作